From efa86e8eda14b429e69fa075eb7871cdbfde4ed4 Mon Sep 17 00:00:00 2001 From: rootiest Date: Sat, 25 Jul 2026 21:06:22 -0400 Subject: [PATCH 01/15] feat(docs): add manualtools library for SSOT frontmatter and ordering --- docs/manualtools.py | 81 +++++++++++++++++++++++++++++++++++++ docs/verify-manual.py | 93 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 docs/manualtools.py create mode 100644 docs/verify-manual.py diff --git a/docs/manualtools.py b/docs/manualtools.py new file mode 100644 index 0000000..463932d --- /dev/null +++ b/docs/manualtools.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 +# Copyright (C) 2026 Rootiest +# SPDX-License-Identifier: AGPL-3.0-or-later +"""Shared helpers for the docs/manual SSOT pipeline. + +Frontmatter parsing, deterministic tree ordering, and heading level shifts. +Used by build-manual.py, split-manual.py, and verify-manual.py. +""" + +import re +from pathlib import Path + +import yaml + +FENCE_RE = re.compile(r"^\s*(```|~~~)") +HEADING_RE = re.compile(r"^(#{1,6})(\s)") + + +def parse(path: Path) -> tuple[dict, str]: + """Split a markdown file into (frontmatter dict, body text). + + Files without a leading `---` block yield an empty dict and the whole + text as body. Body is returned with trailing whitespace stripped. + """ + text = path.read_text() + if not text.startswith("---\n"): + return {}, text.rstrip() + end = text.find("\n---\n", 4) + if end == -1: + return {}, text.rstrip() + fm = yaml.safe_load(text[4:end]) or {} + return fm, text[end + 5 :].lstrip('\n').rstrip() + + +def serialize(fm: dict, body: str) -> str: + """Render a frontmatter dict and body back into markdown text.""" + block = yaml.safe_dump(fm, sort_keys=False, allow_unicode=True).rstrip() + return f"---\n{block}\n---\n\n{body.rstrip()}\n" + + +def shift_headings(body: str, by: int) -> str: + """Add `by` levels to every ATX heading, ignoring fenced code blocks.""" + if by == 0: + return body + out, in_fence = [], False + for line in body.split("\n"): + if FENCE_RE.match(line): + in_fence = not in_fence + if not in_fence: + line = HEADING_RE.sub(lambda m: "#" * (len(m.group(1)) + by) + m.group(2), line) + out.append(line) + return "\n".join(out) + + +def _sort_key(entry: Path) -> tuple: + """Order by sidebar.order when present, else by filename. Stable.""" + target = entry / "index.md" if entry.is_dir() else entry + order = None + if target.exists(): + fm, _ = parse(target) + order = (fm.get("sidebar") or {}).get("order") + return (order is None, order if order is not None else 0, entry.name) + + +def walk(root: Path, depth: int = 0) -> list[tuple[Path, int]]: + """Return ordered (path, depth) pairs for every markdown file under root. + + A directory sorts at the position of its index.md and its children are + emitted immediately afterwards at depth+1. + """ + entries = [e for e in root.iterdir() if e.is_dir() or e.suffix == ".md"] + result: list[tuple[Path, int]] = [] + for entry in sorted(entries, key=_sort_key): + if entry.is_dir(): + index = entry / "index.md" + if index.exists(): + result.append((index, depth)) + result.extend(walk(entry, depth + 1)) + elif entry.name != "index.md" or depth == 0: + result.append((entry, depth)) + return result diff --git a/docs/verify-manual.py b/docs/verify-manual.py new file mode 100644 index 0000000..23f04c7 --- /dev/null +++ b/docs/verify-manual.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 +# Copyright (C) 2026 Rootiest +# SPDX-License-Identifier: AGPL-3.0-or-later +"""Verification checks for the docs/manual SSOT pipeline.""" + +import sys +import tempfile +from pathlib import Path + +import manualtools as mt + + +def test_parse_roundtrip(): + fm = {"title": "Git", "sidebar": {"order": 4}, "helpKeywords": ["git", "gi"]} + body = "## gitig\n\nManages ignore files." + text = mt.serialize(fm, body) + with tempfile.TemporaryDirectory() as d: + p = Path(d) / "t.md" + p.write_text(text) + got_fm, got_body = mt.parse(p) + assert got_fm == fm, f"frontmatter mismatch: {got_fm!r}" + assert got_body == body, f"body mismatch: {got_body!r}" + + +def test_parse_no_frontmatter(): + with tempfile.TemporaryDirectory() as d: + p = Path(d) / "t.md" + p.write_text("# Plain\n\ntext\n") + fm, body = mt.parse(p) + assert fm == {}, f"expected empty frontmatter, got {fm!r}" + assert body == "# Plain\n\ntext", f"body mismatch: {body!r}" + + +def test_shift_headings(): + body = "## a\n\ntext\n\n### b" + assert mt.shift_headings(body, 1) == "### a\n\ntext\n\n#### b" + + +def test_shift_headings_skips_code_fences(): + body = "## a\n\n```\n# not a heading\n```\n\n## b" + got = mt.shift_headings(body, 1) + assert "# not a heading" in got, "code fence content was modified" + assert got.startswith("### a"), f"heading not shifted: {got[:10]!r}" + + +def test_walk_orders_by_sidebar_order_then_filename(): + with tempfile.TemporaryDirectory() as d: + root = Path(d) + (root / "b.md").write_text(mt.serialize({"title": "B", "sidebar": {"order": 1}}, "")) + (root / "a.md").write_text(mt.serialize({"title": "A", "sidebar": {"order": 2}}, "")) + (root / "c.md").write_text(mt.serialize({"title": "C"}, "")) + got = [p.name for p, _ in mt.walk(root)] + assert got == ["b.md", "a.md", "c.md"], f"wrong order: {got}" + + +def test_walk_nests_directory_after_its_index(): + with tempfile.TemporaryDirectory() as d: + root = Path(d) + (root / "01-first.md").write_text(mt.serialize({"title": "First"}, "")) + sub = root / "02-group" + sub.mkdir() + (sub / "index.md").write_text(mt.serialize({"title": "Group"}, "")) + (sub / "01-child.md").write_text(mt.serialize({"title": "Child"}, "")) + (root / "03-last.md").write_text(mt.serialize({"title": "Last"}, "")) + got = [(p.name, depth) for p, depth in mt.walk(root)] + expected = [ + ("01-first.md", 0), + ("index.md", 0), + ("01-child.md", 1), + ("03-last.md", 0), + ] + assert got == expected, f"wrong nesting: {got}" + + +TESTS = [v for k, v in sorted(globals().items()) if k.startswith("test_")] + + +def main() -> int: + failed = 0 + for t in TESTS: + try: + t() + print(f" PASS {t.__name__}") + except AssertionError as e: + print(f" FAIL {t.__name__}: {e}", file=sys.stderr) + failed += 1 + print(f"\n{len(TESTS) - failed}/{len(TESTS)} passed") + return 1 if failed else 0 + + +if __name__ == "__main__": + sys.path.insert(0, str(Path(__file__).parent)) + raise SystemExit(main()) -- 2.52.0 From 3ccc5d22104a9510fd27d8ec2aa14ee58d2c38e1 Mon Sep 17 00:00:00 2001 From: rootiest Date: Sat, 25 Jul 2026 21:11:40 -0400 Subject: [PATCH 02/15] fix(docs/manualtools.py): use removeprefix instead of lstrip for frontmatter parsing Replace .lstrip('\n') with .removeprefix("\n") to preserve body text that legitimately starts with blank lines. The serialize() function inserts exactly one separator newline; removing only that one newline (via removeprefix) rather than all leading newlines (via lstrip) maintains parse/serialize roundtrip losslessness. Adds regression test to verify bodies with leading blank lines roundtrip correctly. --- docs/manualtools.py | 2 +- docs/verify-manual.py | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/manualtools.py b/docs/manualtools.py index 463932d..58bda76 100644 --- a/docs/manualtools.py +++ b/docs/manualtools.py @@ -29,7 +29,7 @@ def parse(path: Path) -> tuple[dict, str]: if end == -1: return {}, text.rstrip() fm = yaml.safe_load(text[4:end]) or {} - return fm, text[end + 5 :].lstrip('\n').rstrip() + return fm, text[end + 5 :].removeprefix("\n").rstrip() def serialize(fm: dict, body: str) -> str: diff --git a/docs/verify-manual.py b/docs/verify-manual.py index 23f04c7..ea44cdf 100644 --- a/docs/verify-manual.py +++ b/docs/verify-manual.py @@ -72,6 +72,18 @@ def test_walk_nests_directory_after_its_index(): assert got == expected, f"wrong nesting: {got}" +def test_parse_roundtrip_body_with_leading_blank_line(): + fm = {"title": "Test"} + body = "\nContent starts after blank line." + text = mt.serialize(fm, body) + with tempfile.TemporaryDirectory() as d: + p = Path(d) / "t.md" + p.write_text(text) + got_fm, got_body = mt.parse(p) + assert got_fm == fm, f"frontmatter mismatch: {got_fm!r}" + assert got_body == body, f"body mismatch: expected {body!r}, got {got_body!r}" + + TESTS = [v for k, v in sorted(globals().items()) if k.startswith("test_")] -- 2.52.0 From 61a82540fbbe42733b538e4cb7e04d44cc366334 Mon Sep 17 00:00:00 2001 From: rootiest Date: Sat, 25 Jul 2026 21:21:37 -0400 Subject: [PATCH 03/15] feat(docs): split fish-config.md into docs/manual SSOT tree --- docs/manual/00-name.md | 8 + docs/manual/00-synopsis.md | 19 + docs/manual/00-table-of-contents.md | 45 ++ docs/manual/01-configuration-variables.md | 142 ++++++ docs/manual/02-path-setup.md | 25 + docs/manual/03-key-bindings.md | 58 +++ docs/manual/04-abbreviations.md | 193 ++++++++ .../05-functions/01-file-and-directory.md | 164 +++++++ docs/manual/05-functions/02-navigation.md | 32 ++ .../05-functions/03-editors-and-viewers.md | 71 +++ .../04-git-and-version-control.md | 90 ++++ .../05-functions/05-package-management.md | 60 +++ .../05-functions/06-dependency-management.md | 47 ++ .../05-functions/07-system-and-monitoring.md | 63 +++ .../05-functions/08-terminal-management.md | 60 +++ docs/manual/05-functions/09-clipboard.md | 32 ++ docs/manual/05-functions/10-network.md | 44 ++ .../05-functions/11-pager-and-logging.md | 47 ++ .../05-functions/12-ai-and-developer-tools.md | 116 +++++ .../05-functions/13-media-and-utilities.md | 54 +++ docs/manual/05-functions/14-miscellaneous.md | 286 ++++++++++++ docs/manual/05-functions/index.md | 10 + docs/manual/06-dependency-catalog.md | 73 +++ docs/manual/07-customization.md | 438 ++++++++++++++++++ docs/manual/08-fisher-plugins.md | 107 +++++ docs/manual/09-installation.md | 43 ++ docs/manual/10-personalization.md | 68 +++ docs/manual/11-viewing-this-manual.md | 78 ++++ docs/manual/index.md | 77 +++ docs/manualtools.py | 9 +- docs/split-manual.py | 149 ++++++ docs/verify-manual.py | 20 + 32 files changed, 2726 insertions(+), 2 deletions(-) create mode 100644 docs/manual/00-name.md create mode 100644 docs/manual/00-synopsis.md create mode 100644 docs/manual/00-table-of-contents.md create mode 100644 docs/manual/01-configuration-variables.md create mode 100644 docs/manual/02-path-setup.md create mode 100644 docs/manual/03-key-bindings.md create mode 100644 docs/manual/04-abbreviations.md create mode 100644 docs/manual/05-functions/01-file-and-directory.md create mode 100644 docs/manual/05-functions/02-navigation.md create mode 100644 docs/manual/05-functions/03-editors-and-viewers.md create mode 100644 docs/manual/05-functions/04-git-and-version-control.md create mode 100644 docs/manual/05-functions/05-package-management.md create mode 100644 docs/manual/05-functions/06-dependency-management.md create mode 100644 docs/manual/05-functions/07-system-and-monitoring.md create mode 100644 docs/manual/05-functions/08-terminal-management.md create mode 100644 docs/manual/05-functions/09-clipboard.md create mode 100644 docs/manual/05-functions/10-network.md create mode 100644 docs/manual/05-functions/11-pager-and-logging.md create mode 100644 docs/manual/05-functions/12-ai-and-developer-tools.md create mode 100644 docs/manual/05-functions/13-media-and-utilities.md create mode 100644 docs/manual/05-functions/14-miscellaneous.md create mode 100644 docs/manual/05-functions/index.md create mode 100644 docs/manual/06-dependency-catalog.md create mode 100644 docs/manual/07-customization.md create mode 100644 docs/manual/08-fisher-plugins.md create mode 100644 docs/manual/09-installation.md create mode 100644 docs/manual/10-personalization.md create mode 100644 docs/manual/11-viewing-this-manual.md create mode 100644 docs/manual/index.md create mode 100644 docs/split-manual.py diff --git a/docs/manual/00-name.md b/docs/manual/00-name.md new file mode 100644 index 0000000..11f3751 --- /dev/null +++ b/docs/manual/00-name.md @@ -0,0 +1,8 @@ +--- +title: Name +manTitle: NAME +man: true +site: false +--- + +fish-config - personal fish shell configuration for Fish 4.x with modern CLI tool integration diff --git a/docs/manual/00-synopsis.md b/docs/manual/00-synopsis.md new file mode 100644 index 0000000..5d2fa97 --- /dev/null +++ b/docs/manual/00-synopsis.md @@ -0,0 +1,19 @@ +--- +title: Synopsis +manTitle: SYNOPSIS +man: true +site: false +--- + +help config [SECTION] + +Open this manual in the best available pager. Optionally jump to a section +by keyword: + + help config keybindings + help config pkg + help config abbreviations + help config logs + +The `help config` syntax integrates with fish's built-in help command. +The underlying `config-help` function is also available directly. diff --git a/docs/manual/00-table-of-contents.md b/docs/manual/00-table-of-contents.md new file mode 100644 index 0000000..52d2205 --- /dev/null +++ b/docs/manual/00-table-of-contents.md @@ -0,0 +1,45 @@ +--- +title: Table Of Contents +manTitle: TABLE OF CONTENTS +man: true +site: false +--- + +1. Configuration Variables + 2. PATH Setup + 3. Key Bindings + 4. Abbreviations + 4.1 Editors + 4.2 Navigation and Listing + 4.3 Git + 4.4 Terminal Windows, Tabs, and Panes + 4.5 Chezmoi + 4.6 Docker + 4.7 Systemctl + 4.8 AI Assistants + 4.9 History Expansion + 4.10 Miscellaneous + 4.11 Shell Aliases + 5. Functions Reference + 5.1 File and Directory + 5.2 Navigation + 5.3 Editors and Viewers + 5.4 Git and Version Control + 5.5 Package Management + 5.6 Dependency Management + 5.7 System and Monitoring + 5.8 Terminal Management + 5.9 Clipboard + 5.10 Network + 5.11 Pager and Logging + 5.12 AI and Developer Tools + 5.13 Media and Utilities + 5.14 Miscellaneous + 6. Dependency Catalog + 7. Customization + 8. Fisher Plugins + 9. Installation + 10. Personalization + 11. Viewing This Manual + +--- diff --git a/docs/manual/01-configuration-variables.md b/docs/manual/01-configuration-variables.md new file mode 100644 index 0000000..65aad02 --- /dev/null +++ b/docs/manual/01-configuration-variables.md @@ -0,0 +1,142 @@ +--- +title: Configuration Variables +manTitle: 1. CONFIGURATION VARIABLES +sidebar: + order: 1 +helpKeywords: +- variables +- config +--- + +These variables are exported from config.fish on every interactive session. +Override them in local.fish (see Section 10, Personalization). + +## Environment Directories (XDG) + + XDG_CONFIG_HOME ~/.config + XDG_CACHE_HOME ~/.cache + XDG_DATA_HOME ~/.local/share + XDG_STATE_HOME ~/.local/state + +Tools that respect XDG are directed to these paths rather than polluting $HOME. + +## Tool Homes (XDG-compliant) + + CARGO_HOME $XDG_DATA_HOME/cargo + RUSTUP_HOME $XDG_DATA_HOME/rustup + GOPATH $XDG_DATA_HOME/go + BUN_INSTALL $XDG_DATA_HOME/bun + NPM_CONFIG_PREFIX $XDG_DATA_HOME/npm-global + GNUPGHOME $XDG_CONFIG_HOME/gnupg + WAKATIME_HOME $XDG_CONFIG_HOME/wakatime + +## Editor and Pager + + EDITOR nvim (falls back to vi if nvim is absent) + VISUAL unset by default; set a GUI editor via local.fish (the edit + function falls back to a GUI chain when VISUAL is empty) + SUDO_EDITOR same as EDITOR + PAGER ov (falls back to less) + +## Scrollback History + + __fish_scrollback_history_dir (unset → ~/.terminal_history) + __fish_scrollback_history_max_files (unset → 100) + SCROLLBACK_HISTORY_DIR ~/.terminal_history (exported mirror) + SCROLLBACK_HISTORY_MAX_FILES 100 (exported mirror) + +The __fish_scrollback_history_* universal variables are the fish-style source +of truth — set them via `config-settings` → Paths, or `set -U` directly. +config.fish exports the SCROLLBACK_HISTORY_* mirrors from them, because the +POSIX wrapper scripts (paru/yay/tmux/zellij logging and _prune_terminal_logs) +read the exported names from the environment. When the __fish_ vars are unset, +the documented defaults are exported. config.fish deliberately does not create +a global source var, which would shadow the universal and stop live edits from +taking effect. + +Scrollback logs accumulate in SCROLLBACK_HISTORY_DIR as timestamped files. +When the count exceeds SCROLLBACK_HISTORY_MAX_FILES the oldest are pruned +automatically on exit. Use `logs` to browse them interactively. + +## Other + + GPG_TTY $(tty) — ensures GPG passphrase prompts work + CLAUDE_CODE_NO_FLICKER 1 — suppress terminal flicker in Claude Code + CDPATH . ~/projects ~ + +Opinionated defaults (CDPATH, PAGER/MANPAGER, Vi mode, command shadows, +terminal integrations) can be switched off per category with universal +variables — see Section 7, "Opinionated Components (Minimal Mode)". + +## Pager Hierarchy + +$PAGER is set to ov when available, falling back to less. The less wrapper +function extends this into a full chain so anything that calls less directly +also benefits: + + $PAGER → ov → less → more → cat + +When bat is installed, man pages are rendered with syntax highlighting: + + MANROFFOPT -c + MANPAGER sh -c 'col -bx | bat -l man -p' + +## Integrations + +### Zoxide + +cd, z, and cdi/zi are all mapped to zoxide-backed navigation. Tab completions +for cd and z blend standard directory entries (CWD and CDPATH) with frecency +results so both familiar and frequently-visited paths appear in one list. + +### DirEnv + +Automatically loads .envrc files on directory change. Takes priority over +the auto-venv logic — if a directory is managed by direnv, the auto-venv +activation is skipped entirely. + +### Auto Python Venv + +When entering a directory that contains a .venv/, the virtualenv is activated +automatically and deactivated when you leave the project tree. + +### WakaTime + +Every shell command is reported to WakaTime for time-tracking. Set +FISH_WAKATIME_DISABLED=1 to disable without removing the plugin. + +### Tailscale + +Full tab completion for the tailscale CLI is provided via conf.d/tailscale.fish. + +### Done Notifications + +Desktop notifications fire when a command takes longer than 10 seconds and +the terminal window is not focused. Configured via fish universal variables: + + __done_min_cmd_duration 10000 ms + __done_notification_urgency_level low + +### Scrollback History + +When running inside Kitty, closing a shell session via exit saves a timestamped +scrollback snapshot to SCROLLBACK_HISTORY_DIR. Files are named: + + scrollback_YYYY-MM-DD_HH-MM-SS.log + +The paru and yay wrappers (auto-generated in ~/.local/bin/) run the command +inside a PTY via script(1) so download progress bars are preserved on screen, +then render the captured terminal animation down to a clean static log via +scripts/clean_progress_log.py (a small terminal-screen emulator that replays +cursor movements, collapses repainted progress frames to their final state, +and preserves ANSI color). If python3 is unavailable the wrapper falls back to +dropping only the script(1) header/footer. Output is saved to: + + paru_YYYY-MM-DD_HH-MM-SS.log + yay_YYYY-MM-DD_HH-MM-SS.log + +Before pruning, _scrollback_prune_junk silently removes empty files, files +with only a single meaningful line (e.g. bare [exited] captures), and Kitty +tab-rename prompt captures. Use exit --no-log (or exit -n) to skip capture. + +--- diff --git a/docs/manual/02-path-setup.md b/docs/manual/02-path-setup.md new file mode 100644 index 0000000..78f8680 --- /dev/null +++ b/docs/manual/02-path-setup.md @@ -0,0 +1,25 @@ +--- +title: Path Setup +manTitle: 2. PATH SETUP +sidebar: + order: 2 +helpKeywords: +- path +--- + +Directories prepended to PATH in this order (first wins): + + ~/.local/bin Standard user-local executables + ~/Applications User-installed standalone apps + ~/scripts Personal shell scripts + ~/bin Cargo binaries (appended — lowest priority) + $BUN_INSTALL/bin Bun runtime and global packages + $NPM_CONFIG_PREFIX/bin Global npm packages + ~/.lmstudio/bin LM Studio CLI + ~/.resend/bin Resend CLI + ~/.fzf/bin fzf binary (git-installed) + +Cargo binaries are intentionally appended (lowest priority) to avoid +shadowing system-installed Rust tools. + +--- diff --git a/docs/manual/03-key-bindings.md b/docs/manual/03-key-bindings.md new file mode 100644 index 0000000..68c4f5f --- /dev/null +++ b/docs/manual/03-key-bindings.md @@ -0,0 +1,58 @@ +--- +title: Key Bindings +manTitle: 3. KEY BINDINGS +sidebar: + order: 3 +helpKeywords: +- keybindings +- bindings +- key-bindings +- keys +--- + +The shell uses Vi key bindings (fish_vi_key_bindings). All custom bindings +are active in Insert, Normal, and Visual modes unless noted. + + Binding Action + ───────────────────────────────────────────────────────────────────── + Ctrl+G Insert the head of the previous command's last path + argument. Equivalent to !$:h in Bash. + Example: previous = "cd /usr/local/bin" + Ctrl+G inserts "/usr/local" + + Ctrl+F Interactive history substitution. Type old/new then + press Ctrl+F to apply s/old/new/ to the previous + command. Equivalent to !!:s/old/new/ in Bash. + Example: previous = "echo this is a test" + type "this is/that was", press Ctrl+F + result = "echo that was a test" + + Ctrl+Alt+U Strip the first token of the current command line, + leaving arguments in place with the cursor at the + start. Useful for quickly retyping the command. + Example: "mkdir new_folder" -> " new_folder" + + Ctrl+Alt+= Evaluate the current command line buffer with + Qalculate! (qalc) and print the result inline. + Requires qalc to be installed. + Example: type "150 * 1.08", press Ctrl+Alt+= + prints 162 + + Ctrl+Enter Smart execute: runs commands instantly without + pressing Enter a second time for certain fast-path + commands (speedtest-fast, etc.). + + @@ FZF inline picker. Type @@ anywhere on the command + line to open an fzf picker and insert a selection + at the cursor position. + +## FZF Bindings (bundled from PatrickF1/fzf.fish) + + Ctrl+R Search command history + Ctrl+Alt+F Search git-tracked files + Ctrl+Alt+L Search git log + Ctrl+Alt+S Search git status + Ctrl+V Search shell variables + Ctrl+Alt+P Search running processes + +--- diff --git a/docs/manual/04-abbreviations.md b/docs/manual/04-abbreviations.md new file mode 100644 index 0000000..f647a14 --- /dev/null +++ b/docs/manual/04-abbreviations.md @@ -0,0 +1,193 @@ +--- +title: Abbreviations +manTitle: 4. ABBREVIATIONS +sidebar: + order: 4 +helpKeywords: +- abbreviations +- abbr +- abbrs +--- + +Abbreviations expand when you press Space or Enter. They are terminal-aware: +some expand differently in Kitty vs WezTerm vs other terminals. + +## 4.1 Editors + + n / nv / neovim nvim + e edit + se sudoedit + k kate + editt Open new tab with nvim (terminal-aware) + cdnv cd ~/.config/nvim + cdnvn cd ~/.config/nvim; nvim + +## 4.2 Navigation and Listing + + l ls + lS lss (sort by size) + lsR lsr (sort by time, oldest first) + lX lx (sort by extension) + lT lt (tree, depth 2) + lsT lstree (full recursive tree) + lzd ld (lazydocker) + cdi zi (interactive zoxide picker) + +## 4.3 Git + + g git + lg lazygit + gitig / git-ignore gi (generate .gitignore) + +## 4.4 Terminal Windows, Tabs, and Panes + +These abbreviations control the terminal emulator. Each has a Kitty +variant and a WezTerm variant; the correct one is inserted based on +$TERM or $TERM_PROGRAM. + + :w New OS window + :wv Split pane horizontally (new pane below) + :wh Split pane vertically (new pane to the right) + :wo Detach current window to its own OS window + :wot Move current pane to a new tab + :t New tab + :tl Set tab title + :tw Set window title + :twk Rename workspace (WezTerm only) + :tp Focus previous tab + :tn Focus next tab + :q Close current pane/window + :Q Close current tab + :sw spwin (spawn new OS window) + +Quick-navigate shortcuts open windows/tabs/panes with preset working dirs: + + :tgk New tab at ~/.config/kitty + :tgn New tab at ~/.config/nvim + :tgf New tab at ~/.config/fish + :tgh New tab at ~ + :tgcz New tab at chezmoi source dir + :tgcm New tab at chezmoi source dir + :tgp New tab at ~/projects + :tgr New tab at / (root) + +Prefixes :wg* and :wvg* / :whg* open OS windows or splits to the same +set of dirs, respectively. + +Prefixes :cd* open tabs with a quick cd shortcut: + + :cdn cd ~/.config/nvim + :cdf cd ~/.config/fish + :cdh cd ~ + :cdcz cd to chezmoi source + :cdp cd ~/projects + +Appending n to any :cd* abbreviation also runs nvim after changing dir. + +## 4.5 Chezmoi + + cm / cme / cmi / cmap / cmad / cmrm / cmcd / + cz / cze / czi / czap / czad / czrm / czcd + + cm / cz chezmoi + cmcd / czcd chezmoi cd + cme / cze chezmoi edit + cmad / czad chezmoi add + cmap / czap chezmoi apply + cmrm / cmf / czrm / czf chezmoi forget + cmi / czi chezmoi init + +## 4.6 Docker + + dcl docker context use default + dcls docker context ls + lzd ld (lazydocker) + +## 4.7 Systemctl + + sc systemctl + ssc sudo systemctl + scu systemctl --user + st systemctl status + scs sudo systemctl start + scr sudo systemctl restart + ssct sudo systemctl start + sscs sudo systemctl stop + sscr sudo systemctl restart + +## 4.8 AI Assistants + + ag agy + ag. agy . + v antigravity-ide + s wezterm ssh (WezTerm only) + +## 4.9 History Expansion + +These are implemented as keybinding helpers, but can also be typed: + + !^ Expand to first argument of previous command + !* Expand to all arguments of previous command + typo_sub Interactive typo substitution (Ctrl+F) + bang_string !string expansion + bang_search !?string search + bang_minus_n !-n (nth-previous command) + +## 4.10 Miscellaneous + + /exit exit + :q Close pane (alias for terminal close) + :Q Close tab + sudu sudo -s + kt kitty (Kitty only) + c cat + speedtest-fast fast-cli + bl bd list + bs bd sync + bC bd create --title + bsh bd show + lb lazybeads + +## 4.11 Shell Aliases + +These aliases are defined in conf.d/tricks.fish via alias (which creates Fish +functions). They are active in all interactive sessions. + +### Navigation + + .. cd .. + ... cd ../.. + .... cd ../../.. + ..... cd ../../../.. + ...... cd ../../../../.. + +### Color Overrides + +Force color output for common tools: + + grep grep --color=auto + fgrep fgrep --color=auto + egrep egrep --color=auto + dir dir --color=auto + vdir vdir --color=auto + +### Safety Wrappers + +Add -i (interactive confirmation) to destructive commands: + + cp cp -i + mv mv -i + +### Archives and Networking + + tarnow tar -acf Create compressed archive (auto-detects format) + untar tar -zxvf Extract a gzip-compressed archive + wget wget -c Resume interrupted downloads by default + tb nc termbin.com 9999 Pipe content to termbin.com for quick sharing + +### System Logs + + jctl journalctl -p 3 -xb Show priority-3 (error) journal entries + from the current boot + +--- diff --git a/docs/manual/05-functions/01-file-and-directory.md b/docs/manual/05-functions/01-file-and-directory.md new file mode 100644 index 0000000..80d3219 --- /dev/null +++ b/docs/manual/05-functions/01-file-and-directory.md @@ -0,0 +1,164 @@ +--- +title: File and Directory +manTitle: 5.1 File and Directory +sidebar: + order: 1 +helpKeywords: +- files +--- + +## cat + + Synopsis: cat [args...] + Wraps bat for files with syntax highlighting and line numbers. + Passes directories to ls. Falls back to /usr/bin/cat. + + cat README.md + cat ~/projects/myapp + +## copy + + Synopsis: copy + Wraps cp, stripping trailing slashes from source directories to + prevent unintended nesting inside the destination. + + copy ./mydir/ ~/backup # copies mydir INTO backup, not backup/mydir/ + +## du + + Synopsis: du [--disk|--dir|--dua] [args...] + Smart disk-usage dispatcher: + --disk force duf (disk-level free/used overview) + --dir force dust (per-directory tree breakdown) + --dua force dua (fast space analyzer) + Without flags, routes to the most appropriate tool by context. + + du ~/Downloads + du --disk + +## dusize + + Synopsis: dusize [dir] + Human-readable disk usage for a directory via du -sh. Defaults to cwd. + + dusize ~/Videos + +## lD + + Synopsis: lD [args...] + Lists directories only in long format with icons. Uses eza, falls back + to lsd, then system ls. + + lD ~/projects + +## ls + + Synopsis: ls [args...] + Lists files in long format with icons and hyperlinks. Uses eza, falls + back to lsd, then system ls. + + ls + ls -a ~/projects + +## lsr + + Synopsis: lsr [args...] + Lists files sorted by modification time, oldest first. Uses eza. + +## lss + + Synopsis: lss [args...] + Lists files sorted by size with gradient color scaling. Uses eza. + +## lstree + + Synopsis: lstree [args...] + Full recursive tree view with icons. Uses eza. + + lstree ~/projects/myapp + +## lt + + Synopsis: lt [args...] + Tree view limited to depth 2 with icons. Uses eza. + + lt ~/projects + +## ltr + + Synopsis: ltr [args...] + Lists files sorted by modification time, oldest first, long format with + age-based gradient scaling. Uses eza. + +## lx + + Synopsis: lx [args...] + Lists files sorted by extension, long format. Uses eza. + +## mkdir + + Synopsis: mkdir [args...] + Interactive mkdir that prints a tree of created directories. + Falls back to mkdir -p silently. + + mkdir ~/projects/myapp/src + +## mkcd + + Synopsis: mkcd [-s] + Creates a directory (including parents) and cd into it. Prints a tree + of created dirs by default; -s/--silent suppresses output. + + mkcd ~/projects/newapp/src + +## poke + + Synopsis: poke [file...] + Creates files via touch, automatically creating any missing parent + directories first. + + poke ~/projects/new/src/main.fish + +## rm + + Synopsis: rm [-e [opts] | -S | args...] + Safe rm wrapper routing to trash: + + (no args) List current trash contents + -e/--empty Empty the trash (pass options to trash-empty) + -S/--secure Permanently delete via rm -rf + fstrim (irreversible) + -r/-R/--recursive Move to trash + Move to trash (safe delete) + + Falls back to /usr/bin/rm when trash is unavailable. + + rm file.txt # moves to trash + rm -e # empty trash + rm -S sensitive.pem # permanent delete + +## rg + + Synopsis: rg [args...] + In Kitty, wraps ripgrep with --hyperlink-format=kitty so search + results are clickable file links in the terminal. Falls back to + system rg in any other terminal. All other arguments pass through + unchanged. + + rg "fish_greeting" ~/.config/fish/ + rg -l "TODO" ~/projects/myapp + +## scrub + + Synopsis: scrub [-a] [-d] [-h] + Recursively removes OS metadata, editor artifacts, compiler output, + and dev caches using fd. + + -a/--aggressive Also removes node_modules, logs, .cache, IDE dirs, + AI session artifacts + -d/--dry-run Print what would be removed without deleting + + scrub + scrub -a + scrub -d + +--- diff --git a/docs/manual/05-functions/02-navigation.md b/docs/manual/05-functions/02-navigation.md new file mode 100644 index 0000000..0cc6ff6 --- /dev/null +++ b/docs/manual/05-functions/02-navigation.md @@ -0,0 +1,32 @@ +--- +title: Navigation +manTitle: 5.2 Navigation +sidebar: + order: 2 +helpKeywords: +- nav-fns +--- + +## cdi + + Synopsis: cdi [query] + Interactive directory picker combining zoxide frecency with fzf. + Equivalent to zi. + + cdi myproject + +## clone + + Synopsis: clone [args...] + Clone a git repository into a new Kitty window. Kitty-only. + + clone https://github.com/user/repo.git + +## clonet + + Synopsis: clonet [args...] + Clone a git repository into a new Kitty tab. Kitty-only. + + clonet https://github.com/user/repo.git + +--- diff --git a/docs/manual/05-functions/03-editors-and-viewers.md b/docs/manual/05-functions/03-editors-and-viewers.md new file mode 100644 index 0000000..58caadf --- /dev/null +++ b/docs/manual/05-functions/03-editors-and-viewers.md @@ -0,0 +1,71 @@ +--- +title: Editors and Viewers +manTitle: 5.3 Editors and Viewers +sidebar: + order: 3 +helpKeywords: +- editors +--- + +## edit + + Synopsis: edit [-V|-t] [-e EDITOR] [-c] [-x TEXT] [-n] [-v|-s] [FILE...] + + Opens files in a text editor, choosing a terminal or GUI editor and + resolving a rich chain of fallbacks. With no --visual/--terminal flag the + mode is auto-detected: interactive terminals use the terminal editor + ($EDITOR), while detached invocations (e.g. desktop shortcuts) use the GUI + editor ($VISUAL). Clipboard contents and literal strings can be opened as + throwaway temp files. Editor output is suppressed unless --verbose. + + GUI fallback chain: zed → antigravity-ide → code → kate → kwrite → + gnome-text-editor → gedit + Terminal fallback chain: nvim → vim → micro → nano → vi + + Options: + -V, --visual Force the GUI editor ($VISUAL or fallbacks) + -t, --terminal Force the terminal editor ($EDITOR or fallbacks) + -e, --editor=X Use a specific editor binary X + -c, --clipboard Open the clipboard contents (as a temp file) + -x, --text=STR Open STR as the contents of a new temp file + -n, --new Force a new window/instance (best-effort) + -v, --verbose Print the launch command and editor output + -s, --silent Suppress all output, including the editor's + -h, --help Show this help message + + edit ~/.config/fish/config.fish + edit --visual notes.txt + edit --terminal --new todo.md + edit --editor=code --clipboard + edit --text="hello world" + +## fc + + Synopsis: fc [command_prefix] + Edit the last shell command (or one matching a prefix) in $EDITOR, + then execute the result. Bash-style fc behaviour. + + fc + fc git + +## less + + Synopsis: less [args...] + Pager wrapper with fallback chain: $PAGER -> ov -> less -> more -> cat. + + less /var/log/syslog + +## rawfish + + Synopsis: rawfish [args...] + Launches Fish with NO_TMUX=1, bypassing any tmux auto-attach logic. + Useful when you need a clean shell without session management. + +## view + + Synopsis: view [args...] + Opens files in nvim read-only mode (-R). Falls back to less. + + view /etc/fstab + +--- diff --git a/docs/manual/05-functions/04-git-and-version-control.md b/docs/manual/05-functions/04-git-and-version-control.md new file mode 100644 index 0000000..bf2e8f6 --- /dev/null +++ b/docs/manual/05-functions/04-git-and-version-control.md @@ -0,0 +1,90 @@ +--- +title: Git and Version Control +manTitle: 5.4 Git and Version Control +sidebar: + order: 4 +helpKeywords: +- git +--- + +## auto-pull + + Synopsis: auto-pull [list] + auto-pull add [PATH] + auto-pull remove + auto-pull status + + Manages the registry of repositories that are background fast-forwarded + when you enter them (see "Auto-pull fast-forward" under the C2 component + reference). The fish-config repo is always covered as a baseline. The + registry is machine-local at `$__fish_user_dots_path/auto-pull.list` (defaults + to `~/.config/.user-dots/fish/auto-pull.list`), one absolute path per line, + and is never committed. Registry management works + even when C2 auto-execution is disabled; only the background sync is gated. + + list Show registered repos (default) + add [PATH] Register PATH's git root (default: current repo) + remove Unregister by basename or exact path + status Show enabled/disabled state, repo count, list path + + cd ~/src/qmk_firmware; and auto-pull add + auto-pull add ~/work/api + auto-pull list + auto-pull remove qmk_firmware + +## branch + + Synopsis: branch + Switches to a local branch, or creates it if it does not exist. + + branch feature/new-ui + +## gi + + Synopsis: gi [-h] [-b] [-p] [-s] [-l] [targets...] + Generates .gitignore content from the gitignore.io API with MD5-based + deduplication (patterns already present are not re-appended). + + -b/--boilerplate Append generic boilerplate first + -p/--prompt Prompt interactively for targets + -s/--stdout Print to stdout instead of appending to .gitignore + -l/--list List all available targets + targets Comma-separated or space-separated target names + + gi python,venv + gi -b -p + gi -s node > .gitignore + +## git-clean + + Synopsis: git-clean [-f] + Fetches and prunes the remote, fast-forwards the current branch, then + deletes local branches whose remote tracking branch has been deleted. + Switches to main/master automatically if the current branch is orphaned. + + -f/--force Force-delete unmerged branches too + + git-clean + git-clean --force + +## gitup + + Synopsis: gitup [args...] + Fetches updates from the remote and shows git status. Extra args are + forwarded to git fetch. + + gitup + gitup --all + +## gitui + + Synopsis: gitui [args...] + Launches gitui with the Catppuccin Frappe theme pre-applied. + +## hist + + Synopsis: hist + Searches shell history with fzf, inserts the selection into the command + line, and copies it to the clipboard via wl-copy. + +--- diff --git a/docs/manual/05-functions/05-package-management.md b/docs/manual/05-functions/05-package-management.md new file mode 100644 index 0000000..9c15231 --- /dev/null +++ b/docs/manual/05-functions/05-package-management.md @@ -0,0 +1,60 @@ +--- +title: Package Management +manTitle: 5.5 Package Management +sidebar: + order: 5 +helpKeywords: +- package-manager +- packages +--- + +## pkg + + Synopsis: pkg [-h] [-i|-u] [package...] + Installs or removes packages using the detected system package manager. + Supports: paru, yay, pacman, apt, dnf, zypper, yum, brew, pkg. + + (no flag) Auto mode: installs missing packages, removes installed ones + -i/--install Force install + -u/--uninstall Force uninstall + + pkg firefox # auto: install if missing, remove if present + pkg -i ripgrep fd # force install + pkg -u cowsay # force uninstall + + The package-installed check uses the correct query for each PM: + pacman/paru/yay pacman -Qi + apt dpkg -s + dnf/zypper/yum rpm -q + brew brew list + pkg pkg info + +## search + + Synopsis: search [args...] + Interactive AUR package search and install via paru or yay. + Arch Linux only. + + search neovim + +## upgrade + + Synopsis: upgrade + Full system upgrade via paru -Syu --noconfirm or yay -Syu --noconfirm. + Arch Linux only. + +## cleanup + + Synopsis: cleanup + Lists and removes orphan packages via pacman, logging their names to + ~/.removed_orphans. Arch Linux only. + +## parur + + Synopsis: parur + Opens an fzf picker of all installed packages (with pacman -Qi previews), + then removes the selected packages via paru or yay. Arch Linux only. + + parur + +--- diff --git a/docs/manual/05-functions/06-dependency-management.md b/docs/manual/05-functions/06-dependency-management.md new file mode 100644 index 0000000..e9b4882 --- /dev/null +++ b/docs/manual/05-functions/06-dependency-management.md @@ -0,0 +1,47 @@ +--- +title: Dependency Management +manTitle: 5.6 Dependency Management +sidebar: + order: 6 +helpKeywords: +- deps +--- + +## fish-deps + + Synopsis: fish-deps [status|install|update|sync] + Unified command for managing all tools this configuration depends on. + + status (default) Show installed/missing status grouped by tier + install Interactively install each missing dependency + update Update all installed dependencies + sync Install missing deps, then update all + + Install method priority (highest to lowest): + 1. git+cargo source build (fish shell itself) + 2. cargo (Rust tools — gets latest crate version) + 3. system PM (paru/apt/brew/etc.) + 4. git clone (fzf) + 5. curl installer (starship, fisher, uv) + + When multiple methods are available you are prompted to choose. + + Dependencies are grouped into three tiers: + + Required fish, fzf, zoxide + Integrations wakatime, tailscale + Recommended cargo, starship, uv, direnv, paru, yay, eza, lsd, bat, + btop, dust, duf, prettyping, ov, ripgrep, lazygit, + lazydocker, trash, kitty, wezterm, python3, yt-dlp + + fish-deps + fish-deps install + fish-deps update + fish-deps sync + +## check_fish_deps + + Synopsis: check_fish_deps + Backwards-compatibility alias for `fish-deps status`. + +--- diff --git a/docs/manual/05-functions/07-system-and-monitoring.md b/docs/manual/05-functions/07-system-and-monitoring.md new file mode 100644 index 0000000..9f47fc3 --- /dev/null +++ b/docs/manual/05-functions/07-system-and-monitoring.md @@ -0,0 +1,63 @@ +--- +title: System and Monitoring +manTitle: 5.7 System and Monitoring +sidebar: + order: 7 +helpKeywords: +- system +--- + +## top + + Synopsis: top [args...] + Launches btop as a modern resource monitor. Falls back to system top. + +## swapstat + + Synopsis: swapstat + Displays a colorized memory report: kernel swappiness, zRAM compression + ratio, zRAM device details, and active swap priorities. + +## sbver + + Synopsis: sbver [--brief] + Verifies Secure Boot signatures on all EFI binaries tracked by sbctl. + Color-codes results: green checkmark (verified), red X (unsigned). + Prints a pass/fail summary. + + --brief Suppress per-file output, show only the summary + + sbver + sbver --brief + +## ports + + Synopsis: ports + Lists active TCP listeners with lsof, showing port/address without + hostname resolution. + +## screensleep + + Synopsis: screensleep + Turns off the display via KDE PowerDevil's "Turn Off Screen" action, + invoked through busctl. + +## lock + + Synopsis: lock + Locks the current desktop session using loginctl lock-session. + +## sudo-toggle + + Synopsis: sudo-toggle + Toggles the sudo NOPASSWD rule on/off via /etc/sudoers.d/nofail-toggle. + Useful for automated tasks that would otherwise require password entry. + +## limine-edit + + Synopsis: limine-edit + Opens /boot/limine.conf in sudoedit, then automatically re-enrolls the + config hash, runs CachyOS boot hooks, and re-signs Secure Boot files. + Combines the edit and sign steps into a single command. + +--- diff --git a/docs/manual/05-functions/08-terminal-management.md b/docs/manual/05-functions/08-terminal-management.md new file mode 100644 index 0000000..a4193df --- /dev/null +++ b/docs/manual/05-functions/08-terminal-management.md @@ -0,0 +1,60 @@ +--- +title: Terminal Management +manTitle: 5.8 Terminal Management +sidebar: + order: 8 +helpKeywords: +- terminal-mgmt +--- + +## tab + + Synopsis: tab [args...] + Opens a new tab in Kitty (kitty @ launch --type=tab), WezTerm + (wezterm cli spawn), or Konsole. Uses current working directory, + or $cdto if set. + + tab + +## split + + Synopsis: split [-h|-v] [command...] + Opens a new pane in Kitty or WezTerm, optionally running a command. + + -h/--horizontal (default) Split below + -v/--vertical Split to the right + + split + split -v nvim README.md + +## spwin + + Synopsis: spwin [args...] + Spawns a new terminal OS window in Kitty (via spawn-window.sh or + kitty @ launch --type=os-window) or WezTerm (wezterm cli spawn --new-window). + +## detach + + Synopsis: detach [-h] [--version] [args...] + Runs a command fully detached via nohup with stdout/stderr discarded. + The command survives the current session. + + detach rsync -a ./data remote:/backup/ + +## bkg + + Synopsis: bkg [args...] + Launches a command in the background via nohup with output discarded. + Simpler than detach; no version flag. + + bkg firefox + +## ssh + + Synopsis: ssh [args...] + In Kitty, wraps ssh with kitten ssh for better terminal integration + (multiplexing, copy/paste support). Falls back to system ssh elsewhere. + + ssh user@host + +--- diff --git a/docs/manual/05-functions/09-clipboard.md b/docs/manual/05-functions/09-clipboard.md new file mode 100644 index 0000000..c2fe7f0 --- /dev/null +++ b/docs/manual/05-functions/09-clipboard.md @@ -0,0 +1,32 @@ +--- +title: Clipboard +manTitle: 5.9 Clipboard +sidebar: + order: 9 +helpKeywords: +- clipboard +--- + +## y + + Synopsis: y [text...] + Copies text to the clipboard via wl-copy (Wayland) or xclip (X11). + Reads from stdin if no arguments given. + + y "hello world" + ls | y + cat file.txt | y + +## p + + Synopsis: p [args...] + Outputs clipboard contents to stdout. + + p | grep foo + p > file.txt + +## paste + + Alias for p. Identical behaviour. + +--- diff --git a/docs/manual/05-functions/10-network.md b/docs/manual/05-functions/10-network.md new file mode 100644 index 0000000..46dd3de --- /dev/null +++ b/docs/manual/05-functions/10-network.md @@ -0,0 +1,44 @@ +--- +title: Network +manTitle: 5.10 Network +sidebar: + order: 10 +helpKeywords: +- network +--- + +## gip + + Synopsis: gip + Fetches and prints both the public IPv4 and IPv6 address via + icanhazip.com. + +## gip4 + + Synopsis: gip4 + Fetches and prints the public IPv4 address. + +## gip6 + + Synopsis: gip6 + Fetches and prints the public IPv6 address. Returns 1 if IPv6 is + unavailable. + +## ping + + Synopsis: ping [args...] + Wraps prettyping with --nolegend. Pass --legend to show the legend. + Falls back to system ping. + + ping google.com + +## qr + + Synopsis: qr [text...] + Generates a UTF-8 QR code from text or stdin. Uses qrencode locally; + falls back to the qrenco.de API. + + qr "https://example.com" + echo "https://example.com" | qr + +--- diff --git a/docs/manual/05-functions/11-pager-and-logging.md b/docs/manual/05-functions/11-pager-and-logging.md new file mode 100644 index 0000000..872fca6 --- /dev/null +++ b/docs/manual/05-functions/11-pager-and-logging.md @@ -0,0 +1,47 @@ +--- +title: Pager and Logging +manTitle: 5.11 Pager and Logging +sidebar: + order: 11 +helpKeywords: +- logging +--- + +## logs + + Synopsis: logs [-c ] + Interactively browses terminal log files sorted newest-first using fzf. + + -c/--category Filter to: scrollback, paru, or yay + + Keybindings inside the fzf browser: + Enter Open in $PAGER + Ctrl+E Open in $EDITOR + Ctrl+D Delete (with confirmation) + ? Toggle keybind help overlay + + Paru and yay logs open in ov with syntax highlighting and sticky section + headers. Scrollback logs open in ov with per-command sticky prompt headers + based on OSC 133 markers. + + logs + logs -c paru + logs -c scrollback + +## smart_exit + + Synopsis: smart_exit [-n] + Closes the shell session. In Kitty, captures the terminal scrollback to + a timestamped log file in $SCROLLBACK_HISTORY_DIR before exiting. + Automatically prunes the oldest logs when the count exceeds + $SCROLLBACK_HISTORY_MAX_FILES. + + -n/--no-log Exit without saving a scrollback log + + The exit builtin is wired to smart_exit for interactive sessions. + Typing exit or Ctrl+D behaves identically to smart_exit. + + smart_exit + smart_exit --no-log + +--- diff --git a/docs/manual/05-functions/12-ai-and-developer-tools.md b/docs/manual/05-functions/12-ai-and-developer-tools.md new file mode 100644 index 0000000..21bbf6b --- /dev/null +++ b/docs/manual/05-functions/12-ai-and-developer-tools.md @@ -0,0 +1,116 @@ +--- +title: AI and Developer Tools +manTitle: 5.12 AI and Developer Tools +sidebar: + order: 12 +helpKeywords: +- ai +--- + +## agy + + Synopsis: agy [args...] + Wrapper for the agy Antigravity AI CLI. Before launching, delegates to + agents-init --agents to ensure AGENTS/ is scaffolded and CLAUDE.md is + symlinked to AGENTS/AGENTS.md in the current project, then forwards all + arguments verbatim to the real agy binary. Command shadow (C1): when + __fish_config_op_aliases (or the master) is disabled, the call is + passed through to the real agy binary unchanged. + + agy chat + agy resume + +## antigravity-ide + + Synopsis: antigravity-ide [args...] + Runs the antigravity-ide editor with warnings filtered. + +## agents-init + + Synopsis: agents-init [--agents | --plugins] + Scaffold an AGENTS/ sub-repository for tracking agent specs, plans, specs, + and dev logs. Creates AGENTS/ as a standalone git repo, moves any existing + AGENTS.md into it, and replaces it with a relative symlink (plus + CLAUDE.md -> AGENTS/AGENTS.md so Claude Code picks up the shared agent + instructions). Consolidates plans/ and specs/ directly under AGENTS/ + (merging any legacy docs/plans, docs/superpowers/plans, or old + AGENTS/plugins/ locations into the canonical AGENTS/), creates + AGENTS/devlogs/, and wires docs/superpowers/{plans,specs} symlinks back to + them. Adds managed paths to .gitignore and auto-commits every change inside + the AGENTS/ sub-repo; pulls first when the sub-repo has an upstream. + Fully idempotent: a second run produces no output and no new commits. + Flags: --agents re-runs only the AGENTS.md / symlink step; --plugins + re-runs only the plans/specs/devlogs wiring step. Called automatically by + the claude and agy wrappers on every invocation. + + Structure versioning: each AGENTS/ repo carries a self-contained version + bumper. AGENTS/.version holds MAJOR.MINOR.PATCH (seeded 1.0.0). Committed + git hooks under AGENTS/.agents-tools/ (wired via core.hooksPath) bump it on + every commit: MINOR (resetting PATCH) when the tracked directory set + changes, PATCH otherwise; MAJOR is manual-only. A prepare-commit-msg hook + appends "(vX.Y.Z)" to the commit subject. Downstream tooling can read + AGENTS/.version - a changed MINOR field signals a structure change. Because + core.hooksPath is a single setting, the local override would otherwise + shadow your global hooks; after bumping the version, each shim chains + (execs) to the global/system core.hooksPath hook of the same name so global + pre-commit / prepare-commit-msg hooks (e.g. ggshield, Git LFS) still run. + The script and hooks are shipped from scripts/agents-tools/ and refreshed + when their version marker is stale. + + agents-init + agents-init --agents + agents-init --plugins + +## claude + + Synopsis: claude [args...] + Wrapper for the claude CLI. Before launching, delegates to agents-init + --agents to ensure AGENTS/ is scaffolded and CLAUDE.md is symlinked to + AGENTS/AGENTS.md in the current project, then forwards all arguments + verbatim to the real claude binary. Command shadow (C1): when + __fish_config_op_aliases (or the master) is disabled, the call is + passed through to the real claude binary unchanged. + + claude + claude --resume + +## claude-docs + + Synopsis: claude-docs + Invokes Claude Code to analyze recent repository changes and update + README.md, ensuring all documented features and examples are accurate. + +## claude-pr + + Synopsis: claude-pr + Invokes Claude Code to run the full PR workflow: create branch, + conventional commit, verification, push, and open a PR with a manual + verification checklist. + +## qc + + Synopsis: qc [prompt...] + Quick-chat wrapper around the aichat LLM CLI that defaults to the "cli" + role - a system prompt tuned for concise, terminal-friendly output. On + first use it installs the bundled role by symlinking + scripts/cli-agent.md to $XDG_CONFIG_HOME/aichat/roles/cli.md (creating + the directory if needed). Inherits every aichat flag and tab completion + (--wraps aichat); passing --role/-r overrides the default role, so qc + forwards to aichat unchanged. The function is only defined when aichat + is installed. Run qc --help for aichat's full flag reference with the + command name rewritten to qc. + + qc "how do I list open ports on linux?" + qc -m ollama:llama3 "explain this error" + qc --role coder "refactor this function" + +## superpowers + + Synopsis: superpowers [on|off] [-g] + Enables or disables the Superpowers plugin for Antigravity and Claude + Code at workspace/project scope (default) or user scope (-g/--global). + + superpowers on + superpowers off -g + +--- diff --git a/docs/manual/05-functions/13-media-and-utilities.md b/docs/manual/05-functions/13-media-and-utilities.md new file mode 100644 index 0000000..49c7f58 --- /dev/null +++ b/docs/manual/05-functions/13-media-and-utilities.md @@ -0,0 +1,54 @@ +--- +title: Media and Utilities +manTitle: 5.13 Media and Utilities +sidebar: + order: 13 +helpKeywords: +- media +--- + +## dng2avif + + Synopsis: dng2avif [-i ] [-o ] [-q ] [-s ] [input.dng] + Converts a DNG raw image to a 10-bit HDR AVIF using an ImageMagick, + ffmpeg, avifenc pipeline with metadata sync via exiftool. + + -i/--input Input file (or positional arg) + -o/--output Output file (default: same name, .avif extension) + -q/--quality Quality 0-100 (default 92) + -s/--speed Encoding speed 0-10 (default 3) + + dng2avif photo.dng + dng2avif -q 85 -s 5 -i shot.dng -o out.avif + +## steam-dl + + Synopsis: steam-dl + Launches Steam under systemd-inhibit, preventing the system from going + idle or sleeping while a download is in progress. + +## spark + + Synopsis: spark [--min=] [--max=] [numbers...] + Renders a Unicode sparkline bar chart for a sequence of numbers. + Reads from stdin if no numbers are given. + + spark 1 1 2 5 14 42 + echo "3 7 2 9 1" | spark + +## yt-dlp + + Synopsis: yt-dlp [args...] URL [URL...] + Wraps yt-dlp, prepending sane defaults: --sponsorblock-remove all, + --embed-subs, --embed-metadata, and --embed-thumbnail. Each default + is suppressed when you already pass that flag, its alias, or its + negation (e.g. --no-embed-thumbnail drops the thumbnail default; + --no-sponsorblock or your own --sponsorblock-remove drops ours). All + other arguments pass through unchanged, and --help falls through to + real yt-dlp. Opinionated component (C1 aliases); when disabled it + passes straight through to the system yt-dlp. + + yt-dlp dQw4w9WgXcQ + yt-dlp --no-embed-thumbnail dQw4w9WgXcQ + +--- diff --git a/docs/manual/05-functions/14-miscellaneous.md b/docs/manual/05-functions/14-miscellaneous.md new file mode 100644 index 0000000..f7049db --- /dev/null +++ b/docs/manual/05-functions/14-miscellaneous.md @@ -0,0 +1,286 @@ +--- +title: Miscellaneous +manTitle: 5.14 Miscellaneous +sidebar: + order: 14 +helpKeywords: +- miscfns +--- + +## config-help + + Synopsis: config-help [SECTION] + config-help [SECTION] --html + config-help [SECTION] --man + config-help -h | --help + + Opens the offline fish shell configuration manual. Without flags, opens + the Markdown source in the best available pager (ov > bat > man > less > + cat). If SECTION is given, jumps to the first heading matching that + keyword (case-insensitive; checks fish-config.index aliases first). + + Flags: + --html / -w Open docs/html/index.html in the default browser. + If SECTION is given, opens at the matching anchor. + Detects the browser via xdg-mime x-scheme-handler/https, + then known binaries, then xdg-open as last resort. + Respects $fish_help_browser and $BROWSER. + --man / -m Open docs/fish-config.1 via man -l directly. + If SECTION is given, jumps to the nearest match. + --help / -h Print usage and navigation key reference. + + config-help keybindings + config-help pkg + config-help --html + config-help pkg --html + config-help --man + config-help pkg --man + + Also available as: help config [SECTION] [FLAGS] + +## open-url + + Synopsis: open-url [-s|--silent] [-v|--verbose] + open-url -h | --help + + Opens a URL or file:// URI in the best available graphical web browser, + backgrounded so it never blocks the terminal. Resolves a real browser + binary rather than deferring to xdg-open, whose MIME dispatch can hand + local text/html files to non-browser apps (e.g. ebook readers). + + Silent by default: prints nothing on success (errors always go to + stderr). Pass --verbose / -v to report which browser is launched; + --silent / -s is accepted for explicitness. + + Resolution order: + 1. $fish_help_browser (explicit override) + 2. $BROWSER (validated; errors if not a command) + 3. xdg-mime default handler for x-scheme-handler/https + 4. First known browser binary found in a built-in list + 5. xdg-open (last resort) + + open-url https://git.rootiest.dev/rootiest/fish-config + open-url "file://$HOME/.config/fish/docs/html/index.html" + + Used internally by config-help --html. + + Typo abbreviation: url-open (expands to open-url on space/enter). + +## repo-open + + Synopsis: repo-open [-p|--print] [-r|--root] + repo-open -h | --help + + Opens the web page for the current repository's `origin` remote in a + browser (via open-url). Deep-links to the current branch when it exists + on the remote — falling back to the remote's default branch (main/master) + otherwise — and to the current sub-directory when run below the repo root. + + The remote URL is normalized from HTTPS and SSH/scp forms + (git@host:owner/repo.git, ssh://…, https://…). The web path layout is + provider-specific; the provider is resolved in order: + + 1. git config browse.provider (per-repo or --global override) + 2. Hostname heuristic (github / gitlab / gitea / bitbucket; + codeberg → gitea) + 3. Default: github-style layout + + Self-hosted hosts the heuristic can't classify (a Gitea/GitLab instance + on a custom domain) need a one-time override: + + git config browse.provider gitea + + Flags: + --print / -p Print the resolved URL instead of opening it. + --root / -r Ignore the current sub-directory; link to the repo root. + --help / -h Show usage. + + repo-open + repo-open --print + repo-open --root + + Typo abbreviation: open-repo (expands to repo-open on space/enter). + +## config-update + + Synopsis: config-update [-h] [-n] [-f] + + Pulls the latest fish configuration from the upstream repository + (https://git.rootiest.dev/rootiest/fish-config.git) into ~/.config/fish. + The remote URL is hard-coded, so this works on fresh clones with no git + remote configured. All git output is suppressed; colored messages report + fetch and merge status. After a successful pull, run `exec fish` to + reload. + + Flags: + --dry-run / -n Fetch and show available commits without applying them. + --force / -f Stash local changes, pull, then restore the stash. + --help / -h Show usage. + + config-update + config-update --dry-run + config-update --force + +## config-settings + + Synopsis: config-settings [-h] + + Opens an interactive TUI for managing fish configuration settings across + four pages, without having to type or remember variable names. Tab cycles + forward through the pages; Shift-Tab cycles backward. + + Universal — opinionated category toggles (C1–C6) + master, persistent (set -U) + Session — the same toggles, current shell only (set -g) + Sponge — sponge history-scrubbing settings: delay, successful exit + codes, purge-only-on-exit, allow-previously-successful, and + extra sensitive variable-name tokens + Paths — scrollback log directory, scrollback max files, the + user-dots path, and the user-dots convenience symlink toggle + (Dots link) + + Toggle rows use ← → (or h/l) along an OFF ← DEFAULT → ON scale; DEFAULT + erases the variable so the master switch / built-in default applies. Value + rows (the path/int/list settings on the Sponge and Paths pages) use Enter to + edit inline; ← / h clears the value back to its default. List rows (e.g. + Extra secret, OK codes) accept values separated by commas and/or whitespace + — "A, B", "A,B" and "A B" all yield the same two entries. Changes apply + immediately. Always available regardless of the __fish_config_opinionated + master state. + + The Sponge and Paths pages always write universal variables — these are + persistent, set-and-forget settings with no per-session scope. Editing a + scrollback row updates both the __fish_scrollback_history_* source-of-truth + variables and the exported SCROLLBACK_HISTORY_* mirrors, so the AUR/tmux/ + zellij log wrappers (which read the exported names) see the change in the + running session. + + The panel adapts to the terminal width automatically, selecting from + four layout tiers (with a 6-column buffer on each side before stepping + up to the next tier) and horizontally centering the box. The panel + redraws within ~0.3 s of a terminal resize with no keypress required. + + COLUMNS >= 90 → 78-wide panel (most detail) + COLUMNS >= 86 → 74-wide panel + COLUMNS >= 82 → 70-wide panel + COLUMNS < 82 → 52-wide panel (default) + + Navigation: + ↑ ↓ / k j Move cursor + ← → / h l Toggle rows: OFF ← DEFAULT → ON + ← / h Value rows: clear to default + Enter Value rows: edit inline (Sponge / Paths pages) + Tab / S-Tab Next / previous page + q / Escape Exit + + Flags: + --help / -h Show usage. + + config-settings + +## config-toggle (deprecated) + + Deprecated alias for config-settings. Prints a deprecation notice to + stderr, then delegates all arguments to config-settings. + + config-toggle + +## bash + + Synopsis: bash [args...] + Switches to bash, with XDG config applied. On exit, $SHELL is reset + back to fish. + +## bd-pull + + Synopsis: bd-pull + Fetches unlinked Gitea issues and creates local Beads entries, updating + issue titles with the assigned Beads IDs. + Requires $GITEA_TOKEN and $GITEA_URL to be set. + + bd-pull rootiest/fish-config + +## cheat + + Synopsis: cheat [args...] + Displays a colorized cheatsheet using cheat -c, falls back to tldr, + then man. + + cheat tar + cheat git + +## cffetch / ffetch + + Synopsis: cffetch [args...] / ffetch [args...] + Clears the screen and displays system information via fastfetch with + the custom config at ~/.fastfetch.jsonc. Falls back to neofetch. + +## dockup + + Synopsis: dockup [-h] [directory] + Pulls latest Docker images, restarts services in the given Docker + Compose project, and prunes dangling images. + + dockup ~/myapp + +## joplin + + Synopsis: joplin [args...] + Runs the Joplin CLI with Node.js deprecation warnings suppressed. + + joplin ls + +## ld + + Synopsis: ld + Launches lazydocker targeting the currently active Docker context, + detected via docker context inspect. + +## replay + + Synopsis: replay + Runs Bash commands and replays any resulting changes to environment + variables, aliases, and the working directory back into the current + Fish session. Useful for sourcing Bash scripts. + + replay "source ~/.bashrc" + replay "export FOO=bar" + +## kitty-logging + + Synopsis: kitty-logging [install|uninstall|status|dismiss] [-h] + + Manages the Kitty scrollback watcher that powers C5 logging. Ships a + canonical watcher and symlinks it into the Kitty config directory (so it + always tracks the source), wiring it into kitty.conf through a + sentinel-marked managed block. Commenting out any conflicting watcher line + avoids double-capture. + + Commands: + install Symlink the watcher and add the managed block + uninstall Remove the managed block and the watcher symlink + status Show wiring, installed watcher version, and C5 state + dismiss Stop the per-session setup reminder + + Runtime capture stays governed by the C5 .logging_disabled sentinel, so + disabling __fish_config_op_logging makes the watcher inert without + uninstalling. Install affects new Kitty windows only. + + Example: + kitty-logging install + kitty-logging status + +## tmux-clean + + Synopsis: tmux-clean + Kills all detached (unattached) tmux sessions, leaving attached ones + running. + +## wake-lock + + Synopsis: wake-lock [args...] + Runs a command under systemd-inhibit, preventing the system from going + idle or sleeping until the command completes. + + wake-lock rsync -avz src/ dest/ + +--- diff --git a/docs/manual/05-functions/index.md b/docs/manual/05-functions/index.md new file mode 100644 index 0000000..de97101 --- /dev/null +++ b/docs/manual/05-functions/index.md @@ -0,0 +1,10 @@ +--- +title: Functions Reference +manTitle: 5. FUNCTIONS REFERENCE +sidebar: + order: 5 +helpKeywords: +- functions +--- + + diff --git a/docs/manual/06-dependency-catalog.md b/docs/manual/06-dependency-catalog.md new file mode 100644 index 0000000..760c5ce --- /dev/null +++ b/docs/manual/06-dependency-catalog.md @@ -0,0 +1,73 @@ +--- +title: Dependency Catalog +manTitle: 6. DEPENDENCY CATALOG +sidebar: + order: 6 +helpKeywords: +- catalog +- deps-catalog +--- + +fish-deps manages these tools. Run `fish-deps` to check status, or +`fish-deps install` to install missing ones. + +## Required + + fish Fish shell >= 4.0 + fzf Fuzzy finder + zoxide Smart cd with frecency + +## Integrations + + wakatime Developer time tracking + tailscale Mesh VPN client + +## Recommended + + cargo Rust toolchain (via rustup); used by fish-deps to install + Rust-based tools and to build fish from source. All paths + are gated on type -q cargo and degrade gracefully. + starship Cross-shell prompt; loaded via type -q starship guard. + Without it the Catppuccin nim-style fallback prompt activates. + uv Python package and project manager (Astral); used by the + fish-from-source build path in fish-deps. All consumers + degrade gracefully without it. + direnv Per-directory environment loading; integration is fully + guarded with type -q direnv. Without it the direnv hook + is simply not loaded and auto-venv activates normally. + paru AUR helper (Arch only; preferred); guarded throughout — + non-Arch systems silently skip AUR-specific paths. + yay AUR helper (Arch only; fallback to paru); same guards apply. + eza Modern ls replacement + lsd ls replacement (fallback to eza) + bat Syntax-highlighted cat + btop Modern resource monitor + dust Disk usage tree (Rust) + duf Disk usage/free overview + prettyping Colorized ping wrapper + ov Modern pager (replaces less) + ripgrep Fast line search + lazygit Terminal git UI + lazydocker Terminal docker UI + trash Safe delete (trash-cli) + kitty GPU-accelerated terminal (primary) + wezterm GPU-accelerated terminal (alternative) + python3 Standalone interpreter — used by the paru/yay log cleaner. + Note: uv does not provide python3 on PATH, and Arch's base + does not include it, so it is listed separately. All + consumers degrade gracefully without it. + yt-dlp Video/media downloader; backs the yt-dlp wrapper function. + Optional — the wrapper falls back to the system yt-dlp and + the rest of the config works without it. + +## Install Methods + +The install priority for each tool: + + cargo Rust tools (eza, lsd, bat, dust, ov, ripgrep, trashy, zoxide, + starship) — always gets the latest crate version + system PM paru / apt / brew / dnf / etc. — for tools without a crate + git clone fzf — installed from GitHub to ~/.fzf/ + curl starship installer, fisher bootstrap, uv installer + +--- diff --git a/docs/manual/07-customization.md b/docs/manual/07-customization.md new file mode 100644 index 0000000..c802fc7 --- /dev/null +++ b/docs/manual/07-customization.md @@ -0,0 +1,438 @@ +--- +title: Customization +manTitle: 7. CUSTOMIZATION +sidebar: + order: 7 +helpKeywords: +- customization +- customize +--- + +## Machine-local Configuration + +Place machine-specific settings that should not be committed to git in: + + $__fish_user_dots_path/local.fish + +`__fish_user_dots_path` defaults to `~/.config/.user-dots/fish`. Set a +custom location with: + + set -U __fish_user_dots_path /path/to/your/dots/fish + +Typical uses: additional PATH entries, local aliases, hostname-specific env +vars, work-specific tool configs. + +For convenience, a git-ignored `user-dots` symlink in the fish config +directory tracks `$__fish_user_dots_path` so the overlay can be browsed from +`~/.config/fish/`. It is created if missing and repointed if the path changes. +Opt out by setting `__fish_user_dots_symlink` to a falsy value, or toggling +"Dots link" off on the config-settings Paths page — this stops generation and +removes any existing link. It only ever manages a symlink and never clobbers a +real file or directory at that path. + +## Secrets and API Keys + + $__fish_user_dots_path/secrets.fish + +Store API tokens, GPG keys, private credentials here. This file is never +committed. It is sourced by local.fish directly, not by config.fish. + +`local.fish` is sourced at the end of config.fish on every interactive +session, so it and its companion secrets.fish can override anything set +earlier. + +## Overriding Configuration Variables + +Any variable set in local.fish after the main config loads takes effect. +Example: to increase the scrollback history limit: + + # in local.fish + set -gx SCROLLBACK_HISTORY_MAX_FILES 200 + +## Fish Universal Variables + +Some settings (fzf colors, theme) are stored in fish_variables via +`set -U`. These are machine-local and git-ignored. Do not commit +fish_variables. + +## Opinionated Components (Minimal Mode) + +Every opinionated piece of this config is active by default but can be +switched off through six category opt-out variables, each evaluated via +__fish_variable_check. Set a variable to any falsy value (0, false, no, +off, n) to disable its category; erase it or set a truthy value (1, true, +yes, on, y) to re-enable. Unset means enabled. + +An explicit per-category truthy value takes precedence over the master +switch: setting __fish_config_opinionated=0 disables all unset categories, +but a category with an explicit truthy value remains enabled regardless. + + Variable Disables + ------------------------------ ------------------------------------ + __fish_config_op_aliases Command shadows and flag injection: + ls->eza, cat->bat, cd->zoxide, + rm->trash, less->ov, top->btop, + ping->prettyping, ssh->kitten, + du->duf/dust, mkdir/bash wrappers, + history timestamps, grep/cp/mv/wget + flag injection, help intercept, claude + AGENTS.md auto-link + __fish_config_op_autoexec Startup side-effects: Fisher + bootstrap, theme apply, paru/yay + wrapper generation, auto venv + activation, WakaTime hook + __fish_config_op_overrides Key and env overrides: Vi mode, + exit->smart_exit, PAGER/MANPAGER, + CDPATH, bang-bang system, autopair, + puffer, starship prompt, theme + colors, FZF_DEFAULT_OPTS, right + prompt + __fish_config_op_integrations Terminal/tool coupling: Kitty/ + WezTerm window abbreviations, done + notifications, spwin/tab/split, + hist, logs, upgrade, WakaTime + __fish_config_op_logging Logging & capture: scrollback + capture on exit, paru/yay AUR log + wrappers, Kitty watcher capture; + sentinel file coordinates + cross-process state + __fish_config_op_greeting Greeting & first-run UI: per-session + fish_greeting override (defines empty + function late in config.fish to + suppress distro greetings such as + CachyOS fastfetch); first-run welcome + banner in conf.d/first_run.fish + +Examples: + + # Disable command shadows only (rm becomes plain rm again): + set -U __fish_config_op_aliases off + + # Full minimal mode — disable all six categories at once: + set -U __fish_config_opinionated 0 + + # Re-enable everything: + set -Ue __fish_config_opinionated + + # Minimal mode but keep the greeting: + set -U __fish_config_opinionated 0 + set -U __fish_config_op_greeting 1 + # (erase both to go back to full-flavor defaults) + +For an interactive alternative to setting these variables by hand, run +config-settings — a full-screen TUI that flips any category (including C5 +logging) on or off, per session or universally. See its entry in Section 5. + +Notes: + + - Command shadows (rm, cat, ls, ...) react immediately; conf.d-level + components (bindings, prompt, abbreviations, hooks) take effect in + new shells. + - With aliases disabled, rm falls back to bare `command rm` — files + are deleted permanently, not trashed. + - Disabled integration commands (spwin, tab, split, hist, logs, + upgrade) print an error naming the variable that disabled them. + - On CachyOS, the distro fish config's own aliases, history override, + and bang-bang bindings are stripped per category as well. + +### Component Reference + +The following tables detail every component in each category. Use this +reference to understand exactly which behaviors change when you toggle a +category variable. + +#### C1 — Command Shadows + +Disabling __fish_config_op_aliases restores standard system behavior for +all of these commands. + + Command / Alias Active behavior Disabled fallback + ─────────────────────────────────────────────────────────────────────────── + ls eza -l -a --icons --hyperlink system ls + cat bat syntax-highlighted; dirs → ls /usr/bin/cat + cd zoxide frecency-based navigation fish builtin cd + rm moves files to trash (recoverable) command rm (permanent) + less $PAGER → ov → less → more → cat system less + du duf (disk overview) or dust (dir tree) system du + top btop resource monitor system top + ping prettyping --nolegend animation system ping + ssh kitten ssh in Kitty terminal system ssh + rg rg --hyperlink-format=kitty system rg + mkdir verbose path-tree display on creation mkdir -p silently + bash XDG bashrc + $SHELL reset on exit system bash + history timestamps prepended to every entry fish builtin history + cp / mv forced -i confirmation prompt cp / mv unmodified + wget forced --continue (resume downloads) system wget + grep/fgrep/egrep forced --color=auto system grep variants + dir / vdir forced --color=auto system dir / vdir + help config intercepts "help config" → config-help fish builtin help + claude auto-links AGENTS.md as CLAUDE.md before launch command claude + edit multi-editor launcher (GUI/term + fallbacks) $EDITOR/nvim/nano/vi + +When C1 is disabled, `rm` uses bare `command rm` with no wrapper — files +are permanently deleted, not trashed. There is no intermediate safety net. + +#### C2 — Startup Side-Effects + +These run automatically without any user action. Disabling +__fish_config_op_autoexec prevents all of them. + + Component Trigger What it does + ─────────────────────────────────────────────────────────────────────────── + Fisher bootstrap First shell only Downloads and installs fisher + Fisher update After bootstrap Installs all fish_plugins entries + Catppuccin Mocha theme First shell only Applies theme via fish_config + paru wrapper Every startup Writes ~/.local/bin/paru wrapper + yay wrapper Every startup Writes ~/.local/bin/yay wrapper + Python venv activation On every cd Sources .venv/bin/activate.fish + WakaTime command hook On every command Reports to WakaTime API + Auto-pull fast-forward On entering a repo Background ff-only git pull + user-dots symlink Every startup Links $__fish_config_dir/user-dots + to $__fish_user_dots_path + +When C2 is disabled: no Fisher install, no theme application, no paru/yay +wrapper generation, no automatic venv activation, no WakaTime reporting, +no auto-pull (the PWD handler is never registered), and the user-dots +convenience symlink is not created. The symlink is git-ignored and only ever +managed as a symlink — a real file or directory at that path is left untouched. +The symlink has its own opt-out independent of C2: set __fish_user_dots_symlink +to a falsy value (or toggle "Dots link" off on the config-settings Paths page) +to stop generating it and remove any existing link — honoured even when C2 is +enabled. Managed by the __fish_user_dots_link helper. +The first-run completion marker (__fish_config_first_run_complete) is still +set so the init does not re-run on subsequent shells. + +Python venv activation fires on every directory change. If a directory uses +direnv (.envrc present), direnv takes priority and auto-venv is skipped for +that directory. + +Auto-pull fast-forwards opted-in repositories in the background when you cd +into them. The fish-config repo is always covered; other repos are added with +the `auto-pull` command (see its entry in the functions reference). It only +ever fast-forwards a clean repo whose branch has an upstream — never rebases, +merges, or overwrites work — so it is a no-op on dirty trees, divergent +branches, or repos without a remote. The handler fires once per repo entry +(not on every sub-directory cd). The registry is machine-local at +`$__fish_user_dots_path/auto-pull.list` (defaults to `~/.config/.user-dots/fish/auto-pull.list`) and is never committed. + +#### C3 — Key and Environment Overrides + +These change fundamental shell behavior: how keys work, which pager opens, +and what the prompt looks like. Disabling __fish_config_op_overrides removes +all of them. + + Override What it replaces or sets + ─────────────────────────────────────────────────────────────────────────── + Vi mode fish_vi_key_bindings replaces default Emacs mode + exit → smart_exit exit wrapper that captures scrollback before closing + PAGER=ov ov used by git, man, and all $PAGER-aware tools + MANPAGER=bat pipeline man pages rendered with syntax highlighting + CDPATH=. ~/projects ~ bare dir names resolve against ~/projects and ~ + Bang-bang system ! and $ keys expand history; !^, !*, !-N, !?str?, + ^old^new abbreviations; six expand_bang_* helpers + Autopair ( [ { " ' auto-close to (), [], {}, "", '' + Puffer key intercepts . ! $ * keys intercepted for smart expansion + Starship prompt fish_prompt replaced by Starship + OSC 133 markers + Catppuccin colors 30+ fish_color_* variables set to Mocha palette + FZF_DEFAULT_OPTS FZF themed to Catppuccin Mocha colors + Right prompt fish_right_prompt: exit code (on failure) + dim timestamp; always rendered; Docker context added when starship+C3 active + +The bang-bang system spans key_bindings.fish, abbr.fish, puffer.fish, and +six expand_bang_*.fish functions. All are gated together — disabling C3 +removes the entire bang-expansion system at once. + +When C3 is disabled, `exit` falls back to `builtin exit` with no scrollback +capture, no Kitty IPC, and no file I/O on exit. The scrollback capture block +is independently controlled by C5 (see below). + +#### C4 — Terminal and Tool Integration + +These features couple the shell to specific external tools. Disabling +__fish_config_op_integrations disables all of them. + + Component Requires + ─────────────────────────────────────────────────────────────────────────── + ~60 Kitty/WezTerm abbrs Active Kitty or WezTerm session + (:w, :wv, :wh, :t, etc.) + Done desktop notifications Graphical desktop with a notification daemon + spwin Kitty or WezTerm + tab Kitty, WezTerm, or Konsole + split Kitty or WezTerm + hist fzf + wl-copy (Wayland clipboard) + logs fzf + ov; reads from ~/.terminal_history/ + upgrade paru or yay (Arch Linux only) + WakaTime hook wakatime CLI and a configured API key + +Disabled integration commands (spwin, tab, split, hist, logs, upgrade) print +a colored error to stderr naming the variable that disabled them rather than +silently failing. + +#### C5 — Logging and Capture + +Five components capture shell output to disk. Disabling +__fish_config_op_logging skips all capture and removes the logging wrappers. + + Component What it captures + ─────────────────────────────────────────────────────────────────────────── + Scrollback capture Terminal session output saved to: + ~/.terminal_history/scrollback_YYYY-MM-DD_HH-MM-SS.log + tmux pane capture Continuous pane stream via pipe-pane, saved to: + ~/.terminal_history/tmux_-w-p_YYYY-MM-DD_HH-MM-SS.log + zellij pane capture Pane scrollback snapshot on shell exit, saved to: + ~/.terminal_history/zellij_-p_YYYY-MM-DD_HH-MM-SS.log + paru wrapper All paru/AUR output captured to: + ~/.terminal_history/paru_YYYY-MM-DD_HH-MM-SS.log + yay wrapper All yay/AUR output captured to: + ~/.terminal_history/yay_YYYY-MM-DD_HH-MM-SS.log + Kitty watcher watcher.py captures scrollback when Kitty closes + +The tmux capture starts automatically when fish launches inside any tmux +pane ($TMUX is set). It uses tmux's native pipe-pane to stream all pane +output directly to disk without an intermediate process. Each fish shell +session gets its own log file; a new log is created on each shell start +(including exec fish and new splits). Before each new log, the oldest +tmux_*.log files are pruned (by modification time) to keep the total within +SCROLLBACK_HISTORY_MAX_FILES, matching the paru/yay wrapper behaviour. + +The zellij capture works differently: Zellij has no live output-streaming +facility like pipe-pane, so the log is taken as a one-shot snapshot when the +shell exits, via `zellij action dump-screen --full --ansi` (the --ansi flag +preserves color). The dump is captured on the fish process's stdout and +written to the log file by fish itself (not via `--path`, which would make the +zellij server write the file). A fish_exit handler (registered whenever +$ZELLIJ is set) writes the pane's full scrollback and then prunes old +zellij_*.log files the same way. Because the capture happens at exit, toggling +__fish_config_op_logging takes effect on the next exit with no restart or +sentinel coordination needed — the C5 guard is re-checked when the handler +fires. + +LIMITATION — zellij capture only fires on a clean shell exit (typing `exit`, +Ctrl-D, or a logout), because that is when the fish_exit handler runs. It does +NOT capture when you close a pane or quit zellij through zellij itself: + + - Closing a pane signals the shell and tears the pane down concurrently, so + even if the handler runs, `dump-screen` may find the pane buffer already + gone. + - Quitting zellij kills the zellij server, and `dump-screen` needs a live + server to read from — there is nothing left to snapshot. + +This is a structural difference from tmux, NOT a bug. tmux streams pane output +to disk continuously via pipe-pane, so whatever was printed is already saved +no matter how the pane dies. Zellij can only snapshot, and the only reliable +snapshot point from the shell is a clean exit. To guarantee a zellij pane is +logged, end the session with `exit` or Ctrl-D rather than zellij's close-pane +or quit actions. + +The Kitty watcher is managed by the kitty-logging command: it symlinks the +watcher (fish-config-watcher.py) into the Kitty config directory and wires it +into kitty.conf via a managed block. Inside Kitty, a non-blocking +per-session reminder points first-time users at `kitty-logging install` until +they install or run `kitty-logging dismiss`. Install affects new Kitty windows +only; runtime disable is still handled by the .logging_disabled sentinel. + +Logging coordination via sentinel file + +C5 uses a sentinel file to synchronize state between the shell and +out-of-process components (the Kitty watcher and all running shells): + + ~/.config/fish/.logging_disabled + +Disabling __fish_config_op_logging: + 1. Creates the sentinel immediately in every open shell. + 2. Removes ~/.local/bin/paru and ~/.local/bin/yay logging wrappers; + bare /usr/bin/paru and /usr/bin/yay are used instead. + 3. Kitty's watcher.py reads the sentinel on each save attempt and + skips capture — no Kitty restart required. + 4. smart_exit stops saving scrollback logs. + 5. Stops tmux pipe-pane capture in every open fish shell inside tmux. + +Re-enabling __fish_config_op_logging: + 1. Removes the sentinel in every open shell. + 2. Regenerates paru/yay logging wrappers in ~/.local/bin/. + 3. Kitty watcher resumes capture on the next session exit. + 4. Restarts tmux pipe-pane capture in every open fish shell inside tmux. + +Changes propagate to all running shells through an event handler that fires +whenever __fish_config_op_logging changes — no shell restart needed. + +Note: C3 and C5 compose independently. C3 controls whether the smart_exit +wrapper is active at all; C5 controls only the scrollback-capture block +inside it. With C3 disabled, exit is plain builtin exit regardless of C5. + +#### C6 — Greeting and First-Run UI + + Component What it shows + ─────────────────────────────────────────────────────────────────────────── + First-run welcome banner One-time message on first interactive session + fish_greeting override Empty function defined late in config.fish to + suppress distro greetings (e.g. CachyOS sets + fish_greeting to fastfetch by default) + +When C6 is disabled, no greeting is printed by this config. Any greeting +set by the distro or other configs runs normally — this config simply does +not override it. + +## Prompt and Theme + +### Starship + +The primary prompt is Starship, initialized by conf.d/starship.fish. +Configure it via ~/.config/starship.toml. + +conf.d/starship.fish defines a fish_prompt wrapper that only activates when +starship is in PATH. It emits OSC 133;A (prompt start) immediately before +Starship renders and OSC 133;B (input start) immediately after, placing both +markers on the prompt line itself. This allows ov to use them as sticky +section headers when browsing scrollback logs. Without Starship, fish's +built-in prompt handles these markers automatically. + +### Catppuccin Fallback Prompt + +When Starship is absent or C3 overrides are disabled, a built-in nim-style +two-line prompt activates from functions/fish_prompt.fish. No external +dependencies — fish builtins only. + +Layout: + + ┬─[user@host:~/path] (main) + ╰─>$ + +Elements: + + user Yellow (Catppuccin Yellow); red if root + @host Blue (local) or Teal (SSH) + ~/path prompt_pwd abbreviation (Catppuccin Text) + (main) Current git branch in Catppuccin Pink; omitted outside repos + ─[V:name] Active Python venv basename; omitted when none + ─[N/I/R/V] Vi-mode indicator when vi bindings are active + ┬─ / ╰─> Connector lines: Catppuccin Green on success, Red on failure + +The right prompt (fish_right_prompt.fish) always renders, regardless of C3 +state. On failure it shows a red ✘ and the exit code; on success it shows +only the dim timestamp. When starship is installed and C3 is enabled, the +active Docker context is also shown (if non-default): + + ✘ 1 󰡨 myctx Fri Jun 12 00:51:21 2026 ← failed, starship+C3 active + ✘ 1 Fri Jun 12 00:51:21 2026 ← failed, fallback prompt + Fri Jun 12 00:51:21 2026 ← success (no ✘) + +### FZF + +FZF is themed to Catppuccin Mocha via FZF_DEFAULT_OPTS set in +integrations/fzf.fish. The colors applied: + + Background: #1E1E2E (base) #313244 (surface0) + Foreground: #CDD6F4 (text) + Highlights: #F38BA8 (red) #CBA6F7 (mauve) #B4BEFE (lavender) + +To customize, override FZF_DEFAULT_OPTS in local.fish. + +### Catppuccin Mocha Syntax Highlighting + +The Catppuccin Mocha theme ships with this config in themes/ and is applied +on first run via `conf.d/first_run.fish`. Colors are stored in fish_variables +(universal). To switch variants, install a different theme from themes/: + + fish_config theme save "Catppuccin Latte" + +--- diff --git a/docs/manual/08-fisher-plugins.md b/docs/manual/08-fisher-plugins.md new file mode 100644 index 0000000..9d3edd6 --- /dev/null +++ b/docs/manual/08-fisher-plugins.md @@ -0,0 +1,107 @@ +--- +title: Fisher Plugins +manTitle: 8. FISHER PLUGINS +sidebar: + order: 8 +helpKeywords: +- plugins +- fisher +--- + +Fisher is bootstrapped automatically on the **first interactive session** via +`conf.d/first_run.fish`. This also applies the Catppuccin Mocha theme and +prints a one-time welcome message (gated by __fish_config_op_greeting; set +it to 0 to suppress). Subsequent sessions skip all first-run logic with zero +overhead. + +To re-trigger first-run initialization (e.g., after a fresh install or for +testing), run: + + set -Ue __fish_config_first_run_complete + +Then open a new shell. + +## Fisher-Managed Plugins + +The following plugins are fully managed by Fisher. Their files are installed +into the repo directory by Fisher and are listed in `.gitignore` — do not +commit them. Fisher installs and updates them automatically. + + jorgebucaran/fisher Plugin manager itself + meaningful-ooo/sponge Remove failed commands from history + +## Sponge History Filtering + +Sponge removes failed commands from history and, via conf.d/sponge_privacy.fish, +also filters privacy-sensitive commands through three layers: + +Layer 1 — Static patterns (universal, persistent across sessions): +Commands matching any of these structural signatures are never recorded: + + --password / --token / --passphrase / --api-key flags with values + Inline env assignments: GITHUB_TOKEN=xxx, MY_API_KEY=abc + Fish set with sensitive names: set -gx GITHUB_TOKEN xxx + URLs with embedded credentials: https://user:pass@host + HTTP Authorization headers: curl -H "Authorization: ..." + Basic auth flags: curl -u user:pass + sshpass, docker login -p, openssl -passin/-passout + +Layer 2 — Dynamic secret values (session globals, refreshed each login): +On the first prompt, after secrets.fish has loaded, the literal values of +all exported variables whose names suggest credentials (TOKEN, PASSWORD, +SECRET, API_KEY, etc.) are collected, regex-escaped, and added as a +session-scoped overlay. Because globals shadow universals in Fish, the +combined list is what sponge sees. Rotating a token takes effect on the +next login automatically. + +Layer 3 — Per-command filter (sponge_filter_secrets): +Catches credentials in variables exported after login, such as tokens +sourced from a project .env file mid-session. + +To add your own persistent patterns: + + set -U -a sponge_regex_patterns 'your-regex-here' + +To mark additional variable NAMES as credential-bearing (so Layer 2 scrubs +their values), add name tokens — via `config-settings` → Sponge, or directly: + + set -U -a __fish_sponge_extra_sensitive ACME_API VAULT_PW + +Tokens are folded into the Layer 2 name match case-insensitively as substrings, +so ACME_API also covers ACME_API_KEY. (The match uses `--entire` to return the +full variable name, so partial-name tokens dereference the right value.) + +The `config-settings` Sponge page also surfaces sponge's own tuning variables — +sponge_delay, sponge_successful_exit_codes, sponge_purge_only_on_exit, and +sponge_allow_previously_successful — so they can be changed without typing +variable names. + +## Bundled Plugin Functionality + +The remaining plugin functionality is bundled directly with this config rather +than managed through Fisher. The bundled versions include customizations for +Fish 4.x compatibility and improved behavior that differ from their upstream +releases. Installing them through Fisher would overwrite these customizations. + +Bundled components and their upstream origins: + + catppuccin/fish → themes/ + conf.d/theme.fish + PatrickF1/fzf.fish → functions/_fzf_*.fish + conf.d/fzf.fish + franciscolourenco/done → conf.d/done.fish + jorgebucaran/autopair.fish → functions/_autopair_*.fish + conf.d/autopair.fish + nickeb96/puffer-fish → functions/_puffer_fish_*.fish + conf.d/puffer.fish + +Do not run `fisher install` for these — it will overwrite the customized +versions. To update their behavior, edit the relevant bundled files directly. + +## fish_plugins Manifest + +The `fish_plugins` file at the config root: + + jorgebucaran/fisher Plugin manager itself + meaningful-ooo/sponge Remove failed commands from history + +To update all Fisher-managed plugins, run `fisher update` or `fish-deps +update` which calls it as its first step. + +--- diff --git a/docs/manual/09-installation.md b/docs/manual/09-installation.md new file mode 100644 index 0000000..554f2ab --- /dev/null +++ b/docs/manual/09-installation.md @@ -0,0 +1,43 @@ +--- +title: Installation +manTitle: 9. INSTALLATION +sidebar: + order: 9 +helpKeywords: +- installation +- install +--- + +This configuration is managed as a git repository. To deploy on a new machine: + + mv ~/.config/fish ~/.config/fish.bak # back up any existing config + git clone https://git.rootiest.dev/rootiest/fish-config.git ~/.config/fish + +Then open a new Fish shell. Fisher installs automatically on first launch +and the Catppuccin Mocha theme is applied. All other plugin functionality is +bundled directly with this config and requires no additional installation. + +## Return Sentinel + +config.fish ends with a return sentinel guard. Any lines appended after it by +a tool's setup command (starship init fish | source, zoxide init fish | source, +etc.) will have no effect. All integrations are managed via conf.d/ files. + +If a new tool's shell integration appears to do nothing, check whether its +setup command appended an init line below the sentinel and create a dedicated +conf.d/.fish instead. + +## Updating + +Pull the latest changes from the upstream repository without needing a +configured git remote: + + config-update Fetch and apply the latest commits from upstream + config-update --dry-run Preview available changes without applying them + config-update --force Stash local changes, pull, then restore the stash + +The remote URL (https://git.rootiest.dev/rootiest/fish-config.git) is +hard-coded, so this works on a fresh clone with no origin configured. All +git output is suppressed. Run exec fish after a successful update to reload. + +--- diff --git a/docs/manual/10-personalization.md b/docs/manual/10-personalization.md new file mode 100644 index 0000000..71b093a --- /dev/null +++ b/docs/manual/10-personalization.md @@ -0,0 +1,68 @@ +--- +title: Personalization +manTitle: 10. PERSONALIZATION +sidebar: + order: 10 +helpKeywords: +- personalization +- personalize +--- + +Sensitive credentials and machine-specific settings are kept out of version +control in a private directory. The path defaults to +`~/.config/.user-dots/fish/` but can be overridden: + + set -U __fish_user_dots_path /path/to/your/dots/fish + +Or use the interactive TUI — run `config-settings` and navigate to the +"Dots Path" row (last row). Press Enter to type a new path, or ← / h to +reset to the default. + +config.fish sources local.fish from that directory on every interactive +session. local.fish is responsible for sourcing its own secrets.fish: + + $__fish_user_dots_path/ + ├── secrets.fish API keys, tokens, passwords, personal identifiers + └── local.fish Machine-specific paths, env vars, and sourcing secrets + +fish_variables (auto-managed by fish) is excluded from this repo via +.gitignore. Do not commit it. + +## secrets.fish + +Store anything you would not commit to a public repo: API keys, auth tokens, +passwords, and personal identifiers. + + set -gx MY_NAME "Your Name" + set -gx MY_EMAIL "you@example.com" + set -gx GPG_RECIPIENT "you@example.com" + set -gx GITHUB_TOKEN ghp_yourTokenHere + set -gx OPENAI_API_KEY sk-proj-yourKeyHere + set -gx GITEA_TOKEN yourGiteaTokenHere + set -gx GITEA_CHOSEN_LOGIN your.gitea.instance + set -gx KOPIA_PASSWORD yourKopiaPassword + +## local.fish + +Store paths and variables specific to one machine — things that would be +wrong on any other system. + + # CDPATH — directories searched by cd + set -gx CDPATH . /home/youruser/projects /home/youruser + + # Path to your shared .gitignore boilerplate + set -gx GITIGNORE_BOILERPLATE ~/.config/git/gitignore_boilerplate + + # SSH shortcuts + abbr -a sshr 'ssh you@your-server.local' + abbr -a sshw 'ssh you@work-server.example.com' + + # Docker context shortcuts + abbr -a dcr 'docker context use my-remote-server' + abbr -a dcw 'docker context use work-server' + +local.fish is sourced at the end of config.fish with an existence check so +the public config works cleanly on any machine without the private repo. +local.fish in turn sources secrets.fish when it exists. + +--- diff --git a/docs/manual/11-viewing-this-manual.md b/docs/manual/11-viewing-this-manual.md new file mode 100644 index 0000000..41340d3 --- /dev/null +++ b/docs/manual/11-viewing-this-manual.md @@ -0,0 +1,78 @@ +--- +title: Viewing This Manual +manTitle: 11. VIEWING THIS MANUAL +sidebar: + order: 11 +helpKeywords: +- viewing +- manual +--- + +## With ov (recommended) + + help config + +ov renders the Markdown with syntax highlighting and section-based +navigation. + + Space next section + ^ previous section + Alt+u toggle section list sidebar + / search forward + n / N next / previous search match + g go to line number + j interactive jump target (line, %, or 'section') + q quit + +## With bat + + bat --language=markdown --paging=always ~/.config/fish/docs/fish-config.md + +## As a man page + + help config --man + help config pkg --man + +Opens the compiled docs/fish-config.1 directly via man -l, bypassing +the pager fallback chain. If a section keyword is given, the pager opens +at the nearest matching heading. The symlink is created once on first +run (like an install step) and MANPATH is set each session, enabling +the standard invocation: + + man fish-config + +NOTE: fish-config (hyphen) is this config's man page. fish_config +(underscore) is fish's built-in browser-based configuration tool — +a completely separate command. Do not mix them up. + +## In the browser (HTML) + + help config --html + help config pkg --html + +Opens docs/html/index.html in the default web browser. If a section +keyword is given, the browser opens directly at the matching anchor +(resolved via docs/html/sitemap.json). Browser detection queries the +system's x-scheme-handler/https MIME entry (via xdg-mime) to find the +real browser binary, then falls back through known browser binaries +(firefox, chromium, vivaldi, etc.), and finally xdg-open as a last +resort. Set $fish_help_browser or $BROWSER to override. + +## As a wiki + +The generated Markdown wiki lives in docs/wiki/. index.md provides the +project overview and a full table of contents. Each section page has a +navigation bar at the top linking to every other section. + +The wiki is auto-generated from this file by the CI pipeline on every +push to main that changes docs/fish-config.md. + +## Jumping to a section + + help config keybindings + help config abbreviations + help config pkg + help config logs + help config fish-deps + +The keyword is matched case-insensitively against section headings. diff --git a/docs/manual/index.md b/docs/manual/index.md new file mode 100644 index 0000000..8385cf4 --- /dev/null +++ b/docs/manual/index.md @@ -0,0 +1,77 @@ +--- +title: Fish Shell Configuration +description: Reference manual for the rootiest fish configuration. +manTitle: DESCRIPTION +sidebar: + order: 0 +helpKeywords: +- description +- autopair +- puffer +- puffer-fish +- logging-events +--- + +A production-grade Fish shell configuration targeting Fish 4.x. It provides: + +- Drop-in replacements for common Unix tools (ls, cat, rm, du, ping, less) +- Deep Kitty and WezTerm terminal integration: tab/window/pane management from + the command line +- Automatic session logging: terminal scrollback, tmux/zellij panes, and + paru/yay output captured to ~/.terminal_history (on by default; see below) +- Automatic Python virtualenv activation on directory change +- Cross-platform package management via pkg and fish-deps +- AI session helpers for Claude Code and Antigravity +- Catppuccin Mocha color theme throughout + +> **CAUTION - SESSION LOGGING IS ON BY DEFAULT** +> +> This configuration silently records terminal output to `~/.terminal_history`: +> Kitty scrollback on window close, live tmux pane streams, zellij pane +> snapshots on exit, and full paru/yay output. These logs can contain command +> output, file contents, and secrets printed to the terminal. Nothing leaves +> your machine, but the files persist locally. +> +> - Disable all logging with: `set -U __fish_config_op_logging off` +> - Prefer a menu? Run the interactive picker: `config-settings` +> - See Section 7 (C5 - Logging and Capture) for the full breakdown. + +The configuration is split across: + + config.fish Main entry point; sets env vars and PATH + conf.d/ + abbr.fish All abbreviations + autopair.fish Auto-pair brackets and quotes (bundled from jorgebucaran/autopair.fish) + cheat.fish cheat.sh tab completions + done.fish Desktop notifications for long commands + first_run.fish One-time init: Fisher bootstrap, theme, welcome + key_bindings.fish Custom key bindings and Vi mode + logging-events.fish C5 --on-variable event handlers; syncs logging state at startup + kitty-watcher-reminder.fish C5 per-session reminder to set up the Kitty watcher + paru-wrapper.fish Auto-generates ~/.local/bin/paru logging wrapper + puffer.fish !! / !$ / ./ expansion (bundled from nickeb96/puffer-fish) + tmux-logging.fish C5 starts tmux pipe-pane capture when fish runs inside tmux + zellij-logging.fish C5 fish_exit handler dumping zellij pane scrollback on exit + sponge_privacy.fish Sponge privacy patterns; filters credentials from history + starship.fish fish_prompt with OSC 133 shell-integration markers + tailscale.fish Tailscale CLI tab completions + theme.fish Catppuccin syntax highlight colors + tricks.fish PATH, bang-bang helpers, bat man pages, aliases + wakatime.fish WakaTime shell hook + yay-wrapper.fish Auto-generates ~/.local/bin/yay logging wrapper + zoxide.fish Zoxide z/zi integration; overrides cd + functions/ Custom functions, one per file, autoloaded + completions/ Tab completion scripts + integrations/ + fzf.fish FZF Catppuccin theme and key binding config + scripts/ + clean_progress_log.py Strips paru/yay typescript animations to clean static logs + agents-tools/ AGENTS.md version-bump script and git hooks (wired via core.hooksPath) + docs/ Offline documentation and compiled man page + fish-config.md Primary source manual (terminal-readable) + fish-config.1 Compiled man page (auto-generated by CI) + fish-config.index Section index for help config navigation + html/ Chunked HTML docs (auto-generated by CI) + wiki/ Markdown wiki (auto-generated by CI) + +--- diff --git a/docs/manualtools.py b/docs/manualtools.py index 58bda76..9f76e59 100644 --- a/docs/manualtools.py +++ b/docs/manualtools.py @@ -39,7 +39,10 @@ def serialize(fm: dict, body: str) -> str: def shift_headings(body: str, by: int) -> str: - """Add `by` levels to every ATX heading, ignoring fenced code blocks.""" + """Add `by` levels to every ATX heading, ignoring fenced code blocks. + + Negative values promote headings. Level is clamped to [1, 6]. + """ if by == 0: return body out, in_fence = [], False @@ -47,7 +50,9 @@ def shift_headings(body: str, by: int) -> str: if FENCE_RE.match(line): in_fence = not in_fence if not in_fence: - line = HEADING_RE.sub(lambda m: "#" * (len(m.group(1)) + by) + m.group(2), line) + line = HEADING_RE.sub( + lambda m: "#" * max(1, min(6, len(m.group(1)) + by)) + m.group(2), line + ) out.append(line) return "\n".join(out) diff --git a/docs/split-manual.py b/docs/split-manual.py new file mode 100644 index 0000000..50fdaa7 --- /dev/null +++ b/docs/split-manual.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python3 +# Copyright (C) 2026 Rootiest +# SPDX-License-Identifier: AGPL-3.0-or-later +"""One-shot migration: docs/fish-config.md -> docs/manual/**. + +Run once, verify with verify-manual.py, then delete this script. +""" + +import re +import shutil +import sys +from pathlib import Path + +import manualtools as mt + +DOCS = Path(__file__).parent +SRC = DOCS / "fish-config.md" +OUT = DOCS / "manual" +INDEX = DOCS / "fish-config.index" + +MAN_ONLY = {"NAME", "SYNOPSIS", "TABLE OF CONTENTS"} +LANDING = "DESCRIPTION" +FUNCTIONS_TITLE_RE = re.compile(r"^\d+\.\s+FUNCTIONS REFERENCE$", re.I) +NUM_PREFIX_RE = re.compile(r"^\d+(\.\d+)*\.?\s+") + + +def slugify(title: str) -> str: + s = NUM_PREFIX_RE.sub("", title).lower() + s = re.sub(r"[^\w\s-]", "", s) + return re.sub(r"[\s_]+", "-", s).strip("-") + + +def display_title(heading: str) -> str: + """Strip leading numbering and normalise SHOUTING to Title Case.""" + t = NUM_PREFIX_RE.sub("", heading).strip() + return t.title() if t.isupper() else t + + +def load_keywords() -> dict[str, list[str]]: + """Reverse fish-config.index into {heading text: [keywords]}.""" + mapping: dict[str, list[str]] = {} + if not INDEX.exists(): + return mapping + for line in INDEX.read_text().splitlines(): + line = line.strip() + if not line or line.startswith("#") or "=" not in line: + continue + keyword, heading = line.split("=", 1) + mapping.setdefault(heading.strip().lstrip("# ").strip(), []).append(keyword.strip()) + return mapping + + +def split_h1(text: str) -> list[tuple[str, str]]: + parts = re.split(r"^# (.+)$", text, flags=re.MULTILINE) + return [(parts[i].strip(), parts[i + 1].strip()) for i in range(1, len(parts), 2)] + + +def split_h2(body: str) -> tuple[str, list[tuple[str, str]]]: + parts = re.split(r"^## (.+)$", body, flags=re.MULTILINE) + intro = parts[0].strip() + subs = [(parts[i].strip(), parts[i + 1].strip()) for i in range(1, len(parts), 2)] + return intro, subs + + +def main() -> int: + if not SRC.exists(): + print(f"error: {SRC} not found", file=sys.stderr) + return 1 + if OUT.exists(): + shutil.rmtree(OUT) + OUT.mkdir(parents=True) + + keywords = load_keywords() + sections = split_h1(SRC.read_text()) + order = 0 + + for heading, body in sections: + kw = keywords.get(heading, []) + if heading in MAN_ONLY: + path = OUT / f"00-{slugify(heading)}.md" + fm = { + "title": display_title(heading), + "manTitle": heading, + "man": True, + "site": False, + } + path.write_text(mt.serialize(fm, body)) + continue + + if heading == LANDING: + fm = { + "title": "Fish Shell Configuration", + "description": "Reference manual for the rootiest fish configuration.", + "manTitle": heading, + "sidebar": {"order": 0}, + } + if kw: + fm["helpKeywords"] = kw + (OUT / "index.md").write_text(mt.serialize(fm, body)) + continue + + order += 1 + if FUNCTIONS_TITLE_RE.match(heading): + # Section 5 explodes into a directory of category files. + d = OUT / f"{order:02d}-functions" + d.mkdir() + intro, subs = split_h2(body) + fm = { + "title": display_title(heading), + "manTitle": heading, + "sidebar": {"order": order}, + } + if kw: + fm["helpKeywords"] = kw + (d / "index.md").write_text(mt.serialize(fm, intro)) + + for i, (sub_heading, sub_body) in enumerate(subs, start=1): + sub_fm = { + "title": display_title(sub_heading), + "manTitle": sub_heading, + "sidebar": {"order": i}, + } + sub_kw = keywords.get(sub_heading, []) + if sub_kw: + sub_fm["helpKeywords"] = sub_kw + # H3 function entries -> H2 so --site can split on them. + promoted = mt.shift_headings(sub_body, -1) + (d / f"{i:02d}-{slugify(sub_heading)}.md").write_text( + mt.serialize(sub_fm, promoted) + ) + continue + + fm = { + "title": display_title(heading), + "manTitle": heading, + "sidebar": {"order": order}, + } + if kw: + fm["helpKeywords"] = kw + (OUT / f"{order:02d}-{slugify(heading)}.md").write_text(mt.serialize(fm, body)) + + count = sum(1 for _ in OUT.rglob("*.md")) + print(f"wrote {count} files to {OUT}") + return 0 + + +if __name__ == "__main__": + sys.path.insert(0, str(Path(__file__).parent)) + raise SystemExit(main()) diff --git a/docs/verify-manual.py b/docs/verify-manual.py index ea44cdf..ec4f3bb 100644 --- a/docs/verify-manual.py +++ b/docs/verify-manual.py @@ -84,6 +84,26 @@ def test_parse_roundtrip_body_with_leading_blank_line(): assert got_body == body, f"body mismatch: expected {body!r}, got {got_body!r}" +def test_manual_tree_exists(): + root = Path(__file__).parent / "manual" + assert root.is_dir(), "docs/manual/ not generated" + assert (root / "index.md").exists(), "docs/manual/index.md missing" + fn = root / "05-functions" + assert fn.is_dir(), "docs/manual/05-functions/ missing" + cats = sorted(p.name for p in fn.glob("*.md") if p.name != "index.md") + assert len(cats) == 14, f"expected 14 function categories, got {len(cats)}: {cats}" + + +def test_function_entries_promoted_to_h2(): + root = Path(__file__).parent / "manual" / "05-functions" + for path in root.glob("*.md"): + if path.name == "index.md": + continue + _, body = mt.parse(path) + assert "\n### " not in f"\n{body}", f"{path.name} still has H3 entries" + assert "\n## " in f"\n{body}", f"{path.name} has no H2 function entries" + + TESTS = [v for k, v in sorted(globals().items()) if k.startswith("test_")] -- 2.52.0 From 63e71ac9ddbd80e7cda9041f09f1810bd2c5a060 Mon Sep 17 00:00:00 2001 From: rootiest Date: Sat, 25 Jul 2026 21:39:48 -0400 Subject: [PATCH 04/15] feat(docs): generate fish-config.md from the manual tree Adds docs/build-manual.py (--concat) and a round-trip test in verify-manual.py that reproduces the pre-migration fish-config.md exactly from docs/manual/. Fixes found by the round-trip check, applied in split-manual.py and re-run to regenerate docs/manual/: - NAME/SYNOPSIS/TABLE OF CONTENTS had no sidebar.order, so they sorted after every numbered section instead of interleaving with DESCRIPTION in original document order. All manual pages now get sidebar.order from a single position counter matching source order. - split_h1/split_h2 used .strip() on section bodies, which also ate leading indentation on the first body line, corrupting the 4-space indented code blocks that open SYNOPSIS and TABLE OF CONTENTS. - The source's leading pandoc metadata block (title/section/header/ date/author) was discarded entirely by the splitter. It's now parsed off via manualtools.parse and stashed on index.md under a "pandoc" key; build-manual.py re-emits it verbatim ahead of the first heading. --- docs/build-manual.py | 70 ++++++++++++++++++++++ docs/manual/00-name.md | 2 + docs/manual/00-synopsis.md | 4 +- docs/manual/00-table-of-contents.md | 4 +- docs/manual/01-configuration-variables.md | 2 +- docs/manual/02-path-setup.md | 2 +- docs/manual/03-key-bindings.md | 2 +- docs/manual/04-abbreviations.md | 2 +- docs/manual/05-functions/index.md | 2 +- docs/manual/06-dependency-catalog.md | 2 +- docs/manual/07-customization.md | 2 +- docs/manual/08-fisher-plugins.md | 2 +- docs/manual/09-installation.md | 2 +- docs/manual/10-personalization.md | 2 +- docs/manual/11-viewing-this-manual.md | 2 +- docs/manual/index.md | 8 ++- docs/split-manual.py | 49 ++++++++++++--- docs/verify-manual.py | 73 +++++++++++++++++++++++ 18 files changed, 211 insertions(+), 21 deletions(-) create mode 100644 docs/build-manual.py diff --git a/docs/build-manual.py b/docs/build-manual.py new file mode 100644 index 0000000..3e95e86 --- /dev/null +++ b/docs/build-manual.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +# Copyright (C) 2026 Rootiest +# SPDX-License-Identifier: AGPL-3.0-or-later +"""Generate publishable artifacts from the docs/manual SSOT. + + --concat one ordered markdown document for pandoc / config-help + --site Starlight content tree + sidebar.json +""" + +import argparse +import sys +from pathlib import Path + +import yaml + +import manualtools as mt + +DOCS = Path(__file__).parent +MANUAL = DOCS / "manual" + + +def build_concat(root: Path) -> str: + """Concatenate the manual into one ordered markdown document. + + Each file contributes `# {manTitle or title}` at a level matching its + depth, and its body headings are demoted by the same amount. + + The root `index.md` (the LANDING page) may carry a `pandoc` key in its + frontmatter — the original document's pandoc metadata block + (title/section/header/date/author). If present, it is re-emitted + verbatim as the leading `---`-fenced block, ahead of every heading. + """ + chunks: list[str] = [] + index_fm, _ = mt.parse(root / "index.md") + pandoc_meta = index_fm.get("pandoc") + if pandoc_meta: + header = yaml.safe_dump(pandoc_meta, sort_keys=False, allow_unicode=True).rstrip() + chunks.append(f"---\n{header}\n---") + for path, depth in mt.walk(root): + fm, body = mt.parse(path) + if not fm.get("man", True): + continue + heading = fm.get("manTitle") or fm.get("title", path.stem) + chunks.append("#" * (depth + 1) + " " + heading) + if body: + chunks.append(mt.shift_headings(body, depth)) + return "\n\n".join(chunks) + "\n" + + +def main() -> int: + ap = argparse.ArgumentParser(description=__doc__) + ap.add_argument("--concat", action="store_true", help="emit the pandoc document") + ap.add_argument("-o", "--output", type=Path, help="write to PATH instead of stdout") + args = ap.parse_args() + + if not args.concat: + ap.error("nothing to do: pass --concat") + + text = build_concat(MANUAL) + if args.output: + args.output.write_text(text) + print(f"wrote {args.output}") + else: + sys.stdout.write(text) + return 0 + + +if __name__ == "__main__": + sys.path.insert(0, str(Path(__file__).parent)) + raise SystemExit(main()) diff --git a/docs/manual/00-name.md b/docs/manual/00-name.md index 11f3751..6f1f6eb 100644 --- a/docs/manual/00-name.md +++ b/docs/manual/00-name.md @@ -3,6 +3,8 @@ title: Name manTitle: NAME man: true site: false +sidebar: + order: 1 --- fish-config - personal fish shell configuration for Fish 4.x with modern CLI tool integration diff --git a/docs/manual/00-synopsis.md b/docs/manual/00-synopsis.md index 5d2fa97..681b193 100644 --- a/docs/manual/00-synopsis.md +++ b/docs/manual/00-synopsis.md @@ -3,9 +3,11 @@ title: Synopsis manTitle: SYNOPSIS man: true site: false +sidebar: + order: 2 --- -help config [SECTION] + help config [SECTION] Open this manual in the best available pager. Optionally jump to a section by keyword: diff --git a/docs/manual/00-table-of-contents.md b/docs/manual/00-table-of-contents.md index 52d2205..74d43ad 100644 --- a/docs/manual/00-table-of-contents.md +++ b/docs/manual/00-table-of-contents.md @@ -3,9 +3,11 @@ title: Table Of Contents manTitle: TABLE OF CONTENTS man: true site: false +sidebar: + order: 4 --- -1. Configuration Variables + 1. Configuration Variables 2. PATH Setup 3. Key Bindings 4. Abbreviations diff --git a/docs/manual/01-configuration-variables.md b/docs/manual/01-configuration-variables.md index 65aad02..7f4fde7 100644 --- a/docs/manual/01-configuration-variables.md +++ b/docs/manual/01-configuration-variables.md @@ -2,7 +2,7 @@ title: Configuration Variables manTitle: 1. CONFIGURATION VARIABLES sidebar: - order: 1 + order: 5 helpKeywords: - variables - config diff --git a/docs/manual/02-path-setup.md b/docs/manual/02-path-setup.md index 78f8680..2c36092 100644 --- a/docs/manual/02-path-setup.md +++ b/docs/manual/02-path-setup.md @@ -2,7 +2,7 @@ title: Path Setup manTitle: 2. PATH SETUP sidebar: - order: 2 + order: 6 helpKeywords: - path --- diff --git a/docs/manual/03-key-bindings.md b/docs/manual/03-key-bindings.md index 68c4f5f..76a8931 100644 --- a/docs/manual/03-key-bindings.md +++ b/docs/manual/03-key-bindings.md @@ -2,7 +2,7 @@ title: Key Bindings manTitle: 3. KEY BINDINGS sidebar: - order: 3 + order: 7 helpKeywords: - keybindings - bindings diff --git a/docs/manual/04-abbreviations.md b/docs/manual/04-abbreviations.md index f647a14..d0e986e 100644 --- a/docs/manual/04-abbreviations.md +++ b/docs/manual/04-abbreviations.md @@ -2,7 +2,7 @@ title: Abbreviations manTitle: 4. ABBREVIATIONS sidebar: - order: 4 + order: 8 helpKeywords: - abbreviations - abbr diff --git a/docs/manual/05-functions/index.md b/docs/manual/05-functions/index.md index de97101..2755f32 100644 --- a/docs/manual/05-functions/index.md +++ b/docs/manual/05-functions/index.md @@ -2,7 +2,7 @@ title: Functions Reference manTitle: 5. FUNCTIONS REFERENCE sidebar: - order: 5 + order: 9 helpKeywords: - functions --- diff --git a/docs/manual/06-dependency-catalog.md b/docs/manual/06-dependency-catalog.md index 760c5ce..2e6ff3c 100644 --- a/docs/manual/06-dependency-catalog.md +++ b/docs/manual/06-dependency-catalog.md @@ -2,7 +2,7 @@ title: Dependency Catalog manTitle: 6. DEPENDENCY CATALOG sidebar: - order: 6 + order: 10 helpKeywords: - catalog - deps-catalog diff --git a/docs/manual/07-customization.md b/docs/manual/07-customization.md index c802fc7..ceece81 100644 --- a/docs/manual/07-customization.md +++ b/docs/manual/07-customization.md @@ -2,7 +2,7 @@ title: Customization manTitle: 7. CUSTOMIZATION sidebar: - order: 7 + order: 11 helpKeywords: - customization - customize diff --git a/docs/manual/08-fisher-plugins.md b/docs/manual/08-fisher-plugins.md index 9d3edd6..685303d 100644 --- a/docs/manual/08-fisher-plugins.md +++ b/docs/manual/08-fisher-plugins.md @@ -2,7 +2,7 @@ title: Fisher Plugins manTitle: 8. FISHER PLUGINS sidebar: - order: 8 + order: 12 helpKeywords: - plugins - fisher diff --git a/docs/manual/09-installation.md b/docs/manual/09-installation.md index 554f2ab..db34247 100644 --- a/docs/manual/09-installation.md +++ b/docs/manual/09-installation.md @@ -2,7 +2,7 @@ title: Installation manTitle: 9. INSTALLATION sidebar: - order: 9 + order: 13 helpKeywords: - installation - install diff --git a/docs/manual/10-personalization.md b/docs/manual/10-personalization.md index 71b093a..81cd4b7 100644 --- a/docs/manual/10-personalization.md +++ b/docs/manual/10-personalization.md @@ -2,7 +2,7 @@ title: Personalization manTitle: 10. PERSONALIZATION sidebar: - order: 10 + order: 14 helpKeywords: - personalization - personalize diff --git a/docs/manual/11-viewing-this-manual.md b/docs/manual/11-viewing-this-manual.md index 41340d3..4e1079a 100644 --- a/docs/manual/11-viewing-this-manual.md +++ b/docs/manual/11-viewing-this-manual.md @@ -2,7 +2,7 @@ title: Viewing This Manual manTitle: 11. VIEWING THIS MANUAL sidebar: - order: 11 + order: 15 helpKeywords: - viewing - manual diff --git a/docs/manual/index.md b/docs/manual/index.md index 8385cf4..2889163 100644 --- a/docs/manual/index.md +++ b/docs/manual/index.md @@ -3,7 +3,13 @@ title: Fish Shell Configuration description: Reference manual for the rootiest fish configuration. manTitle: DESCRIPTION sidebar: - order: 0 + order: 3 +pandoc: + title: FISH-CONFIG + section: 7 + header: Fish Shell Configuration User Manual + date: June 2026 + author: Rootiest helpKeywords: - description - autopair diff --git a/docs/split-manual.py b/docs/split-manual.py index 50fdaa7..aa45f03 100644 --- a/docs/split-manual.py +++ b/docs/split-manual.py @@ -50,15 +50,34 @@ def load_keywords() -> dict[str, list[str]]: return mapping +def _trim_blank_lines(text: str) -> str: + """Drop leading/trailing blank lines without touching interior indentation. + + Plain `.strip()` also eats leading spaces on the first line, which + destroys 4-space-indented code blocks that start immediately after a + heading (e.g. the SYNOPSIS and TABLE OF CONTENTS sections). + """ + lines = text.split("\n") + while lines and lines[0].strip() == "": + lines.pop(0) + while lines and lines[-1].strip() == "": + lines.pop() + return "\n".join(lines) + + def split_h1(text: str) -> list[tuple[str, str]]: parts = re.split(r"^# (.+)$", text, flags=re.MULTILINE) - return [(parts[i].strip(), parts[i + 1].strip()) for i in range(1, len(parts), 2)] + return [ + (parts[i].strip(), _trim_blank_lines(parts[i + 1])) for i in range(1, len(parts), 2) + ] def split_h2(body: str) -> tuple[str, list[tuple[str, str]]]: parts = re.split(r"^## (.+)$", body, flags=re.MULTILINE) - intro = parts[0].strip() - subs = [(parts[i].strip(), parts[i + 1].strip()) for i in range(1, len(parts), 2)] + intro = _trim_blank_lines(parts[0]) + subs = [ + (parts[i].strip(), _trim_blank_lines(parts[i + 1])) for i in range(1, len(parts), 2) + ] return intro, subs @@ -71,10 +90,23 @@ def main() -> int: OUT.mkdir(parents=True) keywords = load_keywords() - sections = split_h1(SRC.read_text()) + # SRC starts with a pandoc metadata block (title/section/header/date/ + # author) consumed by the man-page build. mt.parse() peels it off so it + # isn't silently dropped; it gets stashed on the LANDING (index.md) page + # under "pandoc" and re-emitted verbatim by build-manual.py --concat. + pandoc_meta, src_body = mt.parse(SRC) + sections = split_h1(src_body) order = 0 + # `position` tracks each heading's place in the *original* document, + # including NAME/SYNOPSIS/DESCRIPTION/TABLE OF CONTENTS. It is what + # `sidebar.order` gets set to, so that manualtools.walk() (and thus + # build-manual.py --concat) reproduces the source order exactly. + # `order` (below) is unrelated: it only numbers the *numbered* sections + # (1. CONFIGURATION VARIABLES, 2. PATH SETUP, ...) for filenames. + position = 0 for heading, body in sections: + position += 1 kw = keywords.get(heading, []) if heading in MAN_ONLY: path = OUT / f"00-{slugify(heading)}.md" @@ -83,6 +115,7 @@ def main() -> int: "manTitle": heading, "man": True, "site": False, + "sidebar": {"order": position}, } path.write_text(mt.serialize(fm, body)) continue @@ -92,8 +125,10 @@ def main() -> int: "title": "Fish Shell Configuration", "description": "Reference manual for the rootiest fish configuration.", "manTitle": heading, - "sidebar": {"order": 0}, + "sidebar": {"order": position}, } + if pandoc_meta: + fm["pandoc"] = pandoc_meta if kw: fm["helpKeywords"] = kw (OUT / "index.md").write_text(mt.serialize(fm, body)) @@ -108,7 +143,7 @@ def main() -> int: fm = { "title": display_title(heading), "manTitle": heading, - "sidebar": {"order": order}, + "sidebar": {"order": position}, } if kw: fm["helpKeywords"] = kw @@ -133,7 +168,7 @@ def main() -> int: fm = { "title": display_title(heading), "manTitle": heading, - "sidebar": {"order": order}, + "sidebar": {"order": position}, } if kw: fm["helpKeywords"] = kw diff --git a/docs/verify-manual.py b/docs/verify-manual.py index ec4f3bb..ba95ac3 100644 --- a/docs/verify-manual.py +++ b/docs/verify-manual.py @@ -3,12 +3,27 @@ # SPDX-License-Identifier: AGPL-3.0-or-later """Verification checks for the docs/manual SSOT pipeline.""" +import importlib.util import sys import tempfile from pathlib import Path import manualtools as mt +# docs/build-manual.py follows this repo's hyphenated CLI-script naming +# convention (matching split-manual.py, verify-manual.py), which means it +# cannot satisfy a plain `import build_manual` on its own — Python's import +# statement never treats a hyphen as an underscore. Load it explicitly under +# the name the tests expect and register it in sys.modules; every later +# `import build_manual` (including the one inside test_concat_roundtrips_ +# original below) then finds the cached module instead of touching the path +# finder. +_build_manual_path = Path(__file__).parent / "build-manual.py" +_spec = importlib.util.spec_from_file_location("build_manual", _build_manual_path) +_build_manual = importlib.util.module_from_spec(_spec) +sys.modules["build_manual"] = _build_manual +_spec.loader.exec_module(_build_manual) + def test_parse_roundtrip(): fm = {"title": "Git", "sidebar": {"order": 4}, "helpKeywords": ["git", "gi"]} @@ -104,6 +119,64 @@ def test_function_entries_promoted_to_h2(): assert "\n## " in f"\n{body}", f"{path.name} has no H2 function entries" +def _normalise(text: str) -> str: + """Collapse whitespace so only content differences survive.""" + lines = [ln.rstrip() for ln in text.strip().split("\n")] + return "\n".join(ln for ln in lines if ln != "") + + +def test_concat_roundtrips_original(): + """The concat of manual/ must reproduce the original fish-config.md. + + Prefers docs/fish-config.md.orig (a snapshot of the pre-migration file) + when present. Once that snapshot is deleted post-migration, + docs/fish-config.md IS the concat output regenerated in Step 5, so + falling back to it turns this into an idempotency regression check + instead of going red for a missing file. + """ + import build_manual + + docs = Path(__file__).parent + original = docs / "fish-config.md.orig" + label = "original" + if not original.exists(): + original = docs / "fish-config.md" + label = "fish-config.md" + got = _normalise(build_manual.build_concat(docs / "manual")) + want = _normalise(original.read_text()) + if got != want: + import difflib + + diff = list( + difflib.unified_diff( + want.split("\n"), got.split("\n"), label, "concat", lineterm="", n=1 + ) + )[:40] + raise AssertionError("concat differs from original:\n" + "\n".join(diff)) + + +def test_every_index_keyword_resolves(): + """Every keyword in fish-config.index must match a heading in the concat.""" + import build_manual + + docs = Path(__file__).parent + index = docs / "fish-config.index" + if not index.exists(): + print(" SKIP test_every_index_keyword_resolves (no index file)") + return + concat = build_manual.build_concat(docs / "manual") + headings = {ln.strip() for ln in concat.split("\n") if ln.startswith("#")} + missing = [] + for line in index.read_text().splitlines(): + line = line.strip() + if not line or line.startswith("#") or "=" not in line: + continue + keyword, heading = line.split("=", 1) + if heading.strip() not in headings: + missing.append(f"{keyword.strip()} -> {heading.strip()}") + assert not missing, "unresolvable index keywords:\n " + "\n ".join(missing) + + TESTS = [v for k, v in sorted(globals().items()) if k.startswith("test_")] -- 2.52.0 From beb89e406afec6a16bb5d7b532470d699b87da70 Mon Sep 17 00:00:00 2001 From: rootiest Date: Sat, 25 Jul 2026 21:52:54 -0400 Subject: [PATCH 05/15] fix(docs): move pandoc metadata out of index.md frontmatter index.md is both the man-page LANDING section and a Starlight content page. Astro errors on any frontmatter key outside the fixed man/site/manTitle/helpKeywords schema, so folding the source fish-config.md pandoc header (title/section/header/date/author) onto index.md under a fifth "pandoc" key would break the docs-site build the moment it's scaffolded. Relocate that block to docs/manual/_pandoc.yml: a plain, fence-free YAML file that Astro content collections ignore (leading underscore). split-manual.py now extracts it as raw text (no yaml.safe_load/ safe_dump round-trip) so build-manual.py's --concat re-emits it byte-for-byte instead of merely "verbatim" in comment only. Also guard build_concat against a manual/ tree with no _pandoc.yml/index.md, removing the unconditional index.md parse that previously raised FileNotFoundError on such a tree. Regenerated docs/manual/ via split-manual.py; concat output remains byte-identical to the pre-migration docs/fish-config.md. --- docs/build-manual.py | 20 +++++++++----------- docs/manual/_pandoc.yml | 5 +++++ docs/manual/index.md | 6 ------ docs/split-manual.py | 35 +++++++++++++++++++++++++++++------ 4 files changed, 43 insertions(+), 23 deletions(-) create mode 100644 docs/manual/_pandoc.yml diff --git a/docs/build-manual.py b/docs/build-manual.py index 3e95e86..c62d7b3 100644 --- a/docs/build-manual.py +++ b/docs/build-manual.py @@ -11,8 +11,6 @@ import argparse import sys from pathlib import Path -import yaml - import manualtools as mt DOCS = Path(__file__).parent @@ -25,17 +23,17 @@ def build_concat(root: Path) -> str: Each file contributes `# {manTitle or title}` at a level matching its depth, and its body headings are demoted by the same amount. - The root `index.md` (the LANDING page) may carry a `pandoc` key in its - frontmatter — the original document's pandoc metadata block - (title/section/header/date/author). If present, it is re-emitted - verbatim as the leading `---`-fenced block, ahead of every heading. + `root / "_pandoc.yml"` (if present) holds the original document's + pandoc metadata block (title/section/header/date/author) as raw text, + with no frontmatter fences and no Astro-visible frontmatter key. When + present, its contents are re-emitted byte-for-byte as the leading + `---`-fenced block, ahead of every heading. """ chunks: list[str] = [] - index_fm, _ = mt.parse(root / "index.md") - pandoc_meta = index_fm.get("pandoc") - if pandoc_meta: - header = yaml.safe_dump(pandoc_meta, sort_keys=False, allow_unicode=True).rstrip() - chunks.append(f"---\n{header}\n---") + pandoc_path = root / "_pandoc.yml" + if pandoc_path.exists(): + raw = pandoc_path.read_text().rstrip("\n") + chunks.append(f"---\n{raw}\n---") for path, depth in mt.walk(root): fm, body = mt.parse(path) if not fm.get("man", True): diff --git a/docs/manual/_pandoc.yml b/docs/manual/_pandoc.yml new file mode 100644 index 0000000..057b2b4 --- /dev/null +++ b/docs/manual/_pandoc.yml @@ -0,0 +1,5 @@ +title: FISH-CONFIG +section: 7 +header: Fish Shell Configuration User Manual +date: June 2026 +author: Rootiest diff --git a/docs/manual/index.md b/docs/manual/index.md index 2889163..7e19354 100644 --- a/docs/manual/index.md +++ b/docs/manual/index.md @@ -4,12 +4,6 @@ description: Reference manual for the rootiest fish configuration. manTitle: DESCRIPTION sidebar: order: 3 -pandoc: - title: FISH-CONFIG - section: 7 - header: Fish Shell Configuration User Manual - date: June 2026 - author: Rootiest helpKeywords: - description - autopair diff --git a/docs/split-manual.py b/docs/split-manual.py index aa45f03..9188e4f 100644 --- a/docs/split-manual.py +++ b/docs/split-manual.py @@ -50,6 +50,23 @@ def load_keywords() -> dict[str, list[str]]: return mapping +def extract_raw_frontmatter(path: Path) -> str | None: + """Return the raw text between a file's opening `---` fences, or None. + + Unlike `mt.parse`, this does not round-trip the block through + `yaml.safe_load`/`yaml.safe_dump` — it hands back the exact original + bytes (minus the fence lines themselves) so a later verbatim re-emit + doesn't have to worry about quoting-style or scalar-coercion drift. + """ + text = path.read_text() + if not text.startswith("---\n"): + return None + end = text.find("\n---\n", 4) + if end == -1: + return None + return text[4:end] + + def _trim_blank_lines(text: str) -> str: """Drop leading/trailing blank lines without touching interior indentation. @@ -91,10 +108,16 @@ def main() -> int: keywords = load_keywords() # SRC starts with a pandoc metadata block (title/section/header/date/ - # author) consumed by the man-page build. mt.parse() peels it off so it - # isn't silently dropped; it gets stashed on the LANDING (index.md) page - # under "pandoc" and re-emitted verbatim by build-manual.py --concat. - pandoc_meta, src_body = mt.parse(SRC) + # author) consumed by the man-page build. It has no purpose as an Astro + # page's frontmatter (index.md is also a website content page, and + # Starlight errors on any custom frontmatter key outside the fixed + # man/site/manTitle/helpKeywords schema), so it is extracted as raw text + # and written to docs/manual/_pandoc.yml instead of being folded into + # index.md's frontmatter. The leading underscore keeps Astro content + # collections from treating it as a page. build-manual.py --concat + # reads it back and re-emits it byte-for-byte. + pandoc_raw = extract_raw_frontmatter(SRC) + _, src_body = mt.parse(SRC) sections = split_h1(src_body) order = 0 # `position` tracks each heading's place in the *original* document, @@ -127,11 +150,11 @@ def main() -> int: "manTitle": heading, "sidebar": {"order": position}, } - if pandoc_meta: - fm["pandoc"] = pandoc_meta if kw: fm["helpKeywords"] = kw (OUT / "index.md").write_text(mt.serialize(fm, body)) + if pandoc_raw is not None: + (OUT / "_pandoc.yml").write_text(pandoc_raw.rstrip("\n") + "\n") continue order += 1 -- 2.52.0 From 424a3c76ab7d6ba188f7922f23286898f3f924ba Mon Sep 17 00:00:00 2001 From: rootiest Date: Sat, 25 Jul 2026 21:53:04 -0400 Subject: [PATCH 06/15] fix(docs): make manual round-trip test byte-exact test_concat_roundtrips_original previously compared through _normalise(), which strips trailing whitespace and drops blank lines. Mutation testing showed it still passed after joining chunks with a single newline, deleting all 635 blank lines, and appending trailing double-spaces to every line. Blank lines are load-bearing for pandoc (blank_before_header defaults on), so losing them merges paragraphs and stops headings being headings while the test stays green. Compare the raw got/want text directly to decide pass/fail. Keep _normalise only to build the diff shown on failure, normalising both sides first so whitespace noise doesn't swamp the real difference. If the exact compare fails but the normalised sides match, say so explicitly in the assertion message instead of emitting an empty diff. --- docs/verify-manual.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/docs/verify-manual.py b/docs/verify-manual.py index ba95ac3..1339a7c 100644 --- a/docs/verify-manual.py +++ b/docs/verify-manual.py @@ -126,13 +126,20 @@ def _normalise(text: str) -> str: def test_concat_roundtrips_original(): - """The concat of manual/ must reproduce the original fish-config.md. + """The concat of manual/ must reproduce the original fish-config.md exactly. Prefers docs/fish-config.md.orig (a snapshot of the pre-migration file) when present. Once that snapshot is deleted post-migration, docs/fish-config.md IS the concat output regenerated in Step 5, so falling back to it turns this into an idempotency regression check instead of going red for a missing file. + + The pass/fail decision is an exact (raw-text) comparison, not a + whitespace-normalised one. Blank lines are load-bearing for pandoc + (`blank_before_header` is on by default): losing them merges paragraphs + and stops headings being headings, so a test that tolerated blank-line + or line-joining drift would stay green while the man page silently + broke. `_normalise` is used only afterwards, to build a readable diff. """ import build_manual @@ -142,14 +149,22 @@ def test_concat_roundtrips_original(): if not original.exists(): original = docs / "fish-config.md" label = "fish-config.md" - got = _normalise(build_manual.build_concat(docs / "manual")) - want = _normalise(original.read_text()) + got = build_manual.build_concat(docs / "manual") + want = original.read_text() if got != want: + norm_got = _normalise(got) + norm_want = _normalise(want) + if norm_got == norm_want: + raise AssertionError( + "concat differs from original only in whitespace/blank lines " + "(exact comparison failed, normalised comparison passed) — " + "blank lines are load-bearing for pandoc, this is a real regression" + ) import difflib diff = list( difflib.unified_diff( - want.split("\n"), got.split("\n"), label, "concat", lineterm="", n=1 + norm_want.split("\n"), norm_got.split("\n"), label, "concat", lineterm="", n=1 ) )[:40] raise AssertionError("concat differs from original:\n" + "\n".join(diff)) -- 2.52.0 From e4ef26fe033962124ca5eaf542a4da512e261a71 Mon Sep 17 00:00:00 2001 From: rootiest Date: Sat, 25 Jul 2026 22:01:42 -0400 Subject: [PATCH 07/15] ci(docs): build man page from the manual tree --- .gitea/workflows/build-docs.yml | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/.gitea/workflows/build-docs.yml b/.gitea/workflows/build-docs.yml index 0a5ad63..326f126 100644 --- a/.gitea/workflows/build-docs.yml +++ b/.gitea/workflows/build-docs.yml @@ -5,7 +5,9 @@ on: branches: - main paths: - - "docs/fish-config.md" + - "docs/manual/**" + - "docs/build-manual.py" + - "docs/manualtools.py" jobs: build-docs: @@ -16,8 +18,16 @@ jobs: with: token: ${{ secrets.GITEA_TOKEN }} - - name: Install pandoc - run: sudo apt-get update -qq && sudo apt-get install -y pandoc + - name: Install dependencies + run: | + sudo apt-get update -qq + sudo apt-get install -y pandoc python3-yaml + + - name: Verify manual integrity + run: python3 docs/verify-manual.py + + - name: Generate concatenated markdown + run: python3 docs/build-manual.py --concat -o docs/fish-config.md - name: Compile man page run: | @@ -27,22 +37,11 @@ jobs: docs/fish-config.md \ -o docs/fish-config.1 - - name: Generate chunked HTML docs - run: | - rm -rf docs/html/ - pandoc -f gfm -t chunkedhtml --split-level=1 --toc \ - --include-in-header docs/html-style.html \ - docs/fish-config.md \ - -o docs/html/ - - - name: Generate wiki markdown - run: python3 docs/split-wiki.py - - name: Commit generated docs run: | git config user.name "Gitea Actions" git config user.email "actions@gitea" - git add docs/fish-config.1 docs/html/ docs/wiki/ + git add docs/fish-config.md docs/fish-config.1 git diff --cached --quiet && echo "No changes to commit" && exit 0 - git commit -m "chore(docs): regenerate man page, HTML docs, and wiki" + git commit -m "chore(docs): regenerate manual and man page" git push -- 2.52.0 From 36a03202c68938c87b633427d6206dd8fddf2674 Mon Sep 17 00:00:00 2001 From: rootiest Date: Sat, 25 Jul 2026 22:12:48 -0400 Subject: [PATCH 08/15] fix(ci): regenerate docs before verifying manual integrity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit build-docs.yml ran verify-manual.py before regenerating docs/fish-config.md, so test_concat_roundtrips_original compared a fresh concat of docs/manual/** against the stale, pre-push copy on disk. Any ordinary edit under docs/manual/** — the exact trigger for this workflow's paths filter — failed the job before it ever regenerated anything. Swap the "Generate concatenated markdown" and "Verify manual integrity" steps so regeneration runs first. Verification still gates pandoc and the auto-commit step. Also add docs/verify-manual.py to the paths filter so edits to the integrity checker itself retrigger the job. --- .gitea/workflows/build-docs.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.gitea/workflows/build-docs.yml b/.gitea/workflows/build-docs.yml index 326f126..177025f 100644 --- a/.gitea/workflows/build-docs.yml +++ b/.gitea/workflows/build-docs.yml @@ -8,6 +8,7 @@ on: - "docs/manual/**" - "docs/build-manual.py" - "docs/manualtools.py" + - "docs/verify-manual.py" jobs: build-docs: @@ -23,12 +24,20 @@ jobs: sudo apt-get update -qq sudo apt-get install -y pandoc python3-yaml - - name: Verify manual integrity - run: python3 docs/verify-manual.py - - name: Generate concatenated markdown run: python3 docs/build-manual.py --concat -o docs/fish-config.md + # Regeneration MUST run before verification: verify-manual.py's + # test_concat_roundtrips_original compares a freshly-built concat + # against docs/fish-config.md on disk. Before this step ran, that + # file was still the stale pre-push copy, so any ordinary edit under + # docs/manual/** failed the round-trip check before anything was + # regenerated. Do not reorder this back — verification still gates + # pandoc and the auto-commit below, it just no longer requires a + # contributor to hand-sync the generated file before pushing. + - name: Verify manual integrity + run: python3 docs/verify-manual.py + - name: Compile man page run: | pandoc --standalone \ -- 2.52.0 From c096433b5d8b97af98206deac45aa71e7bf676a0 Mon Sep 17 00:00:00 2001 From: rootiest Date: Sat, 25 Jul 2026 22:27:55 -0400 Subject: [PATCH 09/15] feat(docs-site): scaffold Astro Starlight site Scaffold docs/site/ via `npm create astro@latest ... --template starlight`. Extend the docs collection schema in src/content.config.ts with the four custom frontmatter fields (man, site, manTitle, helpKeywords) needed by the generator in a later task, using z.strictObject so unrecognized keys fail the build instead of being silently stripped by Zod's default behavior. Ignore generated site output (node_modules, dist, .astro, generated content, and sidebar.json) in .gitignore. --- .gitignore | 7 + docs/site/.gitignore | 21 + docs/site/.vscode/extensions.json | 4 + docs/site/.vscode/launch.json | 11 + docs/site/README.md | 49 + docs/site/astro.config.mjs | 26 + docs/site/package-lock.json | 6904 +++++++++++++++++++++++++++++ docs/site/package.json | 17 + docs/site/public/favicon.svg | 1 + docs/site/src/assets/houston.webp | Bin 0 -> 98506 bytes docs/site/src/content.config.ts | 25 + docs/site/tsconfig.json | 5 + 12 files changed, 7070 insertions(+) create mode 100644 docs/site/.gitignore create mode 100644 docs/site/.vscode/extensions.json create mode 100644 docs/site/.vscode/launch.json create mode 100644 docs/site/README.md create mode 100644 docs/site/astro.config.mjs create mode 100644 docs/site/package-lock.json create mode 100644 docs/site/package.json create mode 100644 docs/site/public/favicon.svg create mode 100644 docs/site/src/assets/houston.webp create mode 100644 docs/site/src/content.config.ts create mode 100644 docs/site/tsconfig.json diff --git a/.gitignore b/.gitignore index c086b2d..2c9d321 100644 --- a/.gitignore +++ b/.gitignore @@ -300,3 +300,10 @@ docs/devlogs # ──────────────────────────────────────────────────────── /.cache_ggshield user-dots + +# ──────────────────── Generated Docs Site ─────────────────── +docs/site/node_modules/ +docs/site/dist/ +docs/site/.astro/ +docs/site/src/content/docs/ +docs/site/src/sidebar.json diff --git a/docs/site/.gitignore b/docs/site/.gitignore new file mode 100644 index 0000000..6240da8 --- /dev/null +++ b/docs/site/.gitignore @@ -0,0 +1,21 @@ +# build output +dist/ +# generated types +.astro/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store diff --git a/docs/site/.vscode/extensions.json b/docs/site/.vscode/extensions.json new file mode 100644 index 0000000..22a1505 --- /dev/null +++ b/docs/site/.vscode/extensions.json @@ -0,0 +1,4 @@ +{ + "recommendations": ["astro-build.astro-vscode"], + "unwantedRecommendations": [] +} diff --git a/docs/site/.vscode/launch.json b/docs/site/.vscode/launch.json new file mode 100644 index 0000000..d642209 --- /dev/null +++ b/docs/site/.vscode/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "command": "./node_modules/.bin/astro dev", + "name": "Development server", + "request": "launch", + "type": "node-terminal" + } + ] +} diff --git a/docs/site/README.md b/docs/site/README.md new file mode 100644 index 0000000..1b7f5c3 --- /dev/null +++ b/docs/site/README.md @@ -0,0 +1,49 @@ +# Starlight Starter Kit: Basics + +[![Built with Starlight](https://astro.badg.es/v2/built-with-starlight/tiny.svg)](https://starlight.astro.build) + +``` +npm create astro@latest -- --template starlight +``` + +> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun! + +## 🚀 Project Structure + +Inside of your Astro + Starlight project, you'll see the following folders and files: + +``` +. +├── public/ +├── src/ +│ ├── assets/ +│ ├── content/ +│ │ └── docs/ +│ └── content.config.ts +├── astro.config.mjs +├── package.json +└── tsconfig.json +``` + +Starlight looks for `.md` or `.mdx` files in the `src/content/docs/` directory. Each file is exposed as a route based on its file name. + +Images can be added to `src/assets/` and embedded in Markdown with a relative link. + +Static assets, like favicons, can be placed in the `public/` directory. + +## 🧞 Commands + +All commands are run from the root of the project, from a terminal: + +| Command | Action | +| :------------------------ | :----------------------------------------------- | +| `npm install` | Installs dependencies | +| `npm run dev` | Starts local dev server at `localhost:4321` | +| `npm run build` | Build your production site to `./dist/` | +| `npm run preview` | Preview your build locally, before deploying | +| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` | +| `npm run astro -- --help` | Get help using the Astro CLI | + +## 👀 Want to learn more? + +Check out [Starlight’s docs](https://starlight.astro.build/), read [the Astro documentation](https://docs.astro.build), or jump into the [Astro Discord server](https://astro.build/chat). diff --git a/docs/site/astro.config.mjs b/docs/site/astro.config.mjs new file mode 100644 index 0000000..69b83b3 --- /dev/null +++ b/docs/site/astro.config.mjs @@ -0,0 +1,26 @@ +// @ts-check +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; + +// https://astro.build/config +export default defineConfig({ + integrations: [ + starlight({ + title: 'My Docs', + social: [{ icon: 'github', label: 'GitHub', href: 'https://github.com/withastro/starlight' }], + sidebar: [ + { + label: 'Guides', + items: [ + // Each item here is one entry in the navigation menu. + { label: 'Example Guide', slug: 'guides/example' }, + ], + }, + { + label: 'Reference', + items: [{ autogenerate: { directory: 'reference' } }], + }, + ], + }), + ], +}); diff --git a/docs/site/package-lock.json b/docs/site/package-lock.json new file mode 100644 index 0000000..f7ad3c3 --- /dev/null +++ b/docs/site/package-lock.json @@ -0,0 +1,6904 @@ +{ + "name": "site", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "site", + "version": "0.0.1", + "dependencies": { + "@astrojs/starlight": "^0.41.4", + "astro": "^7.0.2", + "sharp": "^0.34.5" + } + }, + "node_modules/@astrojs/compiler-binding": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding/-/compiler-binding-0.3.1.tgz", + "integrity": "sha512-DaAUj29AIBU2XdJ8uwcab8lW5O2pk9pY8AXkcMw0sw77nVa3oeTYRcO+Dvbbpoexf6ThMc0FMWYCQ/wN1/T7oQ==", + "license": "MIT", + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@astrojs/compiler-binding-darwin-arm64": "0.3.1", + "@astrojs/compiler-binding-darwin-x64": "0.3.1", + "@astrojs/compiler-binding-linux-arm64-gnu": "0.3.1", + "@astrojs/compiler-binding-linux-arm64-musl": "0.3.1", + "@astrojs/compiler-binding-linux-x64-gnu": "0.3.1", + "@astrojs/compiler-binding-linux-x64-musl": "0.3.1", + "@astrojs/compiler-binding-wasm32-wasi": "0.3.1", + "@astrojs/compiler-binding-win32-arm64-msvc": "0.3.1", + "@astrojs/compiler-binding-win32-x64-msvc": "0.3.1" + } + }, + "node_modules/@astrojs/compiler-binding-darwin-arm64": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-darwin-arm64/-/compiler-binding-darwin-arm64-0.3.1.tgz", + "integrity": "sha512-IEmEF2fUIlTHtpeE/isyEGVOB14cEyh/LZOFYt6wn3jNyVpdC8aR5OZ+RzFUR/f+8ZDM1LaMwZKvoA7eMyJeFw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-darwin-x64": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-darwin-x64/-/compiler-binding-darwin-x64-0.3.1.tgz", + "integrity": "sha512-GF2kIxjpPDLsn94zbZNMsxEmkU828QqnmM7kiQJnaooS3jmI+I7kk6+oI6EpwOsK3femCMdcm+wmOsEqtGrmjQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-linux-arm64-gnu": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-arm64-gnu/-/compiler-binding-linux-arm64-gnu-0.3.1.tgz", + "integrity": "sha512-XJL3SDmOtVrqFhCirNcHwE91+IesJqlgNo23I4qW9QUYfwzm/TBZuH61fgqsb1ttgR1mMYz6ooPWs0JDhwMqpQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-linux-arm64-musl": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-arm64-musl/-/compiler-binding-linux-arm64-musl-0.3.1.tgz", + "integrity": "sha512-xqE8BVbDoBueK/B47w30PtkVofUWJKGkwoMVE+EOMLf11rnoANxIAdA9FPqY+rng4oNI5ndHGsri1yPj2k8vZQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-linux-x64-gnu": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-x64-gnu/-/compiler-binding-linux-x64-gnu-0.3.1.tgz", + "integrity": "sha512-1y0StU1qiCuDFH3rmbRJXcxdfHxFPrES1Rd+RLffosvUR7I2cH5SF5SFnBN9vXpzpkmyElZm3Yr47iJBPN7vVA==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-linux-x64-musl": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-x64-musl/-/compiler-binding-linux-x64-musl-0.3.1.tgz", + "integrity": "sha512-16q0fYf7kpbmdObZEeZJEup8hQv/whgNwVjrSvT8umrKwLDSnNIWiQpm09lQQu6bweZB0XyIvHwlPitvJhC+hg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-wasm32-wasi": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-wasm32-wasi/-/compiler-binding-wasm32-wasi-0.3.1.tgz", + "integrity": "sha512-cB456shIwDv/PrVT+2QG7LFndpHkVge5HjqADKZgGaAc9JHVktCtjSrcdkRQ+3tbkPazNKaTLRjXLIiz2NIx9g==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.1.6" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@astrojs/compiler-binding-win32-arm64-msvc": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-win32-arm64-msvc/-/compiler-binding-win32-arm64-msvc-0.3.1.tgz", + "integrity": "sha512-ur/9+If/yTE69mmeX5MqSZndL0HOyx67GeNZUy3N7wVdWpLz9UTJXwyWS4UR2PUQHitghjsM5xoX0Ge56WRVQQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-win32-x64-msvc": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-win32-x64-msvc/-/compiler-binding-win32-x64-msvc-0.3.1.tgz", + "integrity": "sha512-k0W+kDBzDkNZOqu4kElDvCOIbKw5Ut9S1WZ1Krj3KTgNuBERNKXsMMsRLLcbgfdMdbe7bTekQLshZrrvmYpmwA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-rs": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-rs/-/compiler-rs-0.3.1.tgz", + "integrity": "sha512-aT7xkgsbNoS6nriY5qKpbihK43slFHO41iqgHCTdOvn1ifaQxLCc5yXy+6GzAtiafoaC1zA7OwVXCXMsvUZOkg==", + "license": "MIT", + "dependencies": { + "@astrojs/compiler-binding": "0.3.1" + }, + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/@astrojs/internal-helpers": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.10.1.tgz", + "integrity": "sha512-5phcroT/vmOOrYuuAxtkbPixy5hePtlz9i8K4OeDv3dNK6/UQRuXPOSRTxIOBbUY5Sonw2UaxjbuVc43Mcir6Q==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.4", + "@types/mdast": "^4.0.4", + "js-yaml": "^4.1.1", + "picomatch": "^4.0.4", + "retext-smartypants": "^6.2.0", + "shiki": "^4.0.2", + "smol-toml": "^1.6.0", + "unified": "^11.0.5" + } + }, + "node_modules/@astrojs/markdown-remark": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-7.2.1.tgz", + "integrity": "sha512-jPVNIqTvk+yKviikszv/Y1U4jGUSKpp/Nw48QZV4qjWgp70j4Lkq3lhSDRbWwCfgKvEyO9GHuVbV1dM2WYXy1w==", + "license": "MIT", + "dependencies": { + "@astrojs/internal-helpers": "0.10.1", + "@astrojs/prism": "4.0.2", + "github-slugger": "^2.0.0", + "hast-util-from-html": "^2.0.3", + "hast-util-to-text": "^4.0.2", + "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", + "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/markdown-satteri": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-satteri/-/markdown-satteri-0.3.4.tgz", + "integrity": "sha512-6Lvt/bQZEBW+zzdhPblvfZEy5PGEYJaUsUqaCgwHeRPxZJL1gc9I+DRLKWJjjYTWDzVUTzXlMq4WwSK+X34CVw==", + "license": "MIT", + "dependencies": { + "@astrojs/internal-helpers": "0.10.1", + "@astrojs/prism": "4.0.2", + "github-slugger": "^2.0.0", + "hast-util-from-html": "^2.0.3", + "satteri": "^0.9.1" + } + }, + "node_modules/@astrojs/mdx": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-7.0.3.tgz", + "integrity": "sha512-RxyIwU0uFam5ftwqKOjpIdhnFxZ/kEikeimLyQy3eGXbHT8WgRGzzesOIHVU8+m9TY8ag5WVOyvV24/GyqPdPQ==", + "license": "MIT", + "dependencies": { + "@astrojs/internal-helpers": "0.10.1", + "@astrojs/markdown-remark": "7.2.1", + "@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": { + "@astrojs/markdown-satteri": "^0.3.1", + "astro": "^7.0.0" + }, + "peerDependenciesMeta": { + "@astrojs/markdown-satteri": { + "optional": true + } + } + }, + "node_modules/@astrojs/prism": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-4.0.2.tgz", + "integrity": "sha512-KTivpmnz6lDsC6o9H4+DNm2SrE/GHzw8cNAvEJwAvUT+eoaEnn/4NtbDNfRRaxaJHdp15gf+tfHAWiXR4wB3BA==", + "license": "MIT", + "dependencies": { + "prismjs": "^1.30.0" + }, + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/@astrojs/sitemap": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@astrojs/sitemap/-/sitemap-3.7.3.tgz", + "integrity": "sha512-f8euLVsyeAmAkSm/1M2Kb8sL8byQmfgbvBNaHFItCheTj/IpiJYSEWVcqDHZ/yEHxiS7+w87mQkzwZaPHmk5GA==", + "license": "MIT", + "dependencies": { + "sitemap": "^9.0.0", + "stream-replace-string": "^2.0.0", + "zod": "^4.3.6" + } + }, + "node_modules/@astrojs/starlight": { + "version": "0.41.4", + "resolved": "https://registry.npmjs.org/@astrojs/starlight/-/starlight-0.41.4.tgz", + "integrity": "sha512-cRCKZhM2BKYViCakBiN68aVwPn5qj/XtMMq//G54xOWdXXcvic1gMMEI+veNlIKOqqC4QmIjcjk4jiFtlZ3mMg==", + "license": "MIT", + "dependencies": { + "@astrojs/markdown-satteri": "^0.3.2", + "@astrojs/mdx": "^7.0.0", + "@astrojs/sitemap": "^3.7.2", + "@pagefind/default-ui": "^1.3.0", + "@types/hast": "^3.0.4", + "@types/js-yaml": "^4.0.9", + "@types/mdast": "^4.0.4", + "astro-expressive-code": "^0.44.0", + "bcp-47": "^2.1.0", + "hast-util-from-html": "^2.0.3", + "hast-util-select": "^6.0.4", + "hast-util-to-string": "^3.0.1", + "hastscript": "^9.0.1", + "i18next": "^26.0.7", + "js-yaml": "^4.1.1", + "klona": "^2.0.6", + "magic-string": "^0.30.21", + "mdast-util-directive": "^3.1.0", + "mdast-util-to-markdown": "^2.1.2", + "mdast-util-to-string": "^4.0.0", + "pagefind": "^1.5.2", + "rehype": "^13.0.2", + "rehype-format": "^5.0.1", + "remark-directive": "^4.0.0", + "satteri": "^0.9.1", + "ultrahtml": "^1.6.0", + "unified": "^11.0.5", + "unist-util-visit": "^5.1.0", + "vfile": "^6.0.3" + }, + "peerDependencies": { + "@astrojs/markdown-remark": "^7.2.0", + "astro": "^7.0.2" + }, + "peerDependenciesMeta": { + "@astrojs/markdown-remark": { + "optional": true + } + } + }, + "node_modules/@astrojs/telemetry": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.3.tgz", + "integrity": "sha512-C1TLn5sPJr0x4vk56piHWKbnqlEB8BKyte5Y45V02U+D7BGO5eMqZDH5aPjnkXQWJggvmsTXxH03QMZ9NgWLzQ==", + "license": "MIT", + "dependencies": { + "ci-info": "^4.4.0", + "dset": "^3.1.4", + "is-docker": "^4.0.0", + "package-manager-detector": "^1.6.0" + }, + "engines": { + "node": "18.20.8 || ^20.3.0 || >=22.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bruits/satteri-darwin-arm64": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-darwin-arm64/-/satteri-darwin-arm64-0.9.5.tgz", + "integrity": "sha512-iw4nZgx9v30lWo/MTngQqi1pI78KI0DnkSm+lVJGYdmPLgAyDNJigVhpG42/Iq55A6c1Ll8q66ljyyRiQUxwow==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@bruits/satteri-darwin-x64": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-darwin-x64/-/satteri-darwin-x64-0.9.5.tgz", + "integrity": "sha512-6T26Z5Kf3cFW2PSlk9p7zT7yVxvuBSiJvYyz9u8KjYwMTqZyIDOj2wDyNpxKV4+6yUVG7rddq2QwvG/8LJA2+Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@bruits/satteri-linux-arm64-gnu": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-arm64-gnu/-/satteri-linux-arm64-gnu-0.9.5.tgz", + "integrity": "sha512-u51id17uJwNEMK9nBlICsq6U31c+XVqQueVBkwRIzZG+gMpS8TOJctt5h5Wz33Z8xnMdTd+adtACVz0yHgGuOA==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@bruits/satteri-linux-arm64-musl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-arm64-musl/-/satteri-linux-arm64-musl-0.9.5.tgz", + "integrity": "sha512-v39HxiwGC5Rqm01HksP6+5Y+xKLPlsuVFgIgpEAo+SiQ22c+mJVhS3u7Z6ePAKdhL5NJoK1xq70kLz3L13AhpQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@bruits/satteri-linux-x64-gnu": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-x64-gnu/-/satteri-linux-x64-gnu-0.9.5.tgz", + "integrity": "sha512-F3uO8uFp3pAP5ZGXttwvh57GS7s0lL953tnNdyI2gRyP4kOOkp6pyGojNJzCjkDvWI2Cvb9iNrKok3aqQPauAw==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@bruits/satteri-linux-x64-musl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-x64-musl/-/satteri-linux-x64-musl-0.9.5.tgz", + "integrity": "sha512-bicEqglLlz++mWyADaZoP0JY20s4vDfLjaPYgQqC+NI4zZLTOOg1T4GB8aqtc822Pqji8SQBmSrTb7CrP8i08Q==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@bruits/satteri-wasm32-wasi": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-wasm32-wasi/-/satteri-wasm32-wasi-0.9.5.tgz", + "integrity": "sha512-zauAuMwfPnKPUkd4AFixRFpXdgKwP2mKgxrIIo2gJzW0/ZneF9dbHnLkojSpaBnCCp7VUL1hIi5WWZvB1CqmAQ==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.11.1", + "@emnapi/runtime": "1.11.1", + "@napi-rs/wasm-runtime": "^1.1.6" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@bruits/satteri-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", + "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@bruits/satteri-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", + "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@bruits/satteri-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", + "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@bruits/satteri-win32-arm64-msvc": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-win32-arm64-msvc/-/satteri-win32-arm64-msvc-0.9.5.tgz", + "integrity": "sha512-SrfE7NEsgZjBvU3c+RR6oQRu0ToXY5uVJEbieXEF0YTctIV2zAVlbaMjWLts074QCgh3a+XHWkR/lWh2VH2LUg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@bruits/satteri-win32-x64-msvc": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-win32-x64-msvc/-/satteri-win32-x64-msvc-0.9.5.tgz", + "integrity": "sha512-5Kw9ZAtTGS8WHizyn+CJhjjfIQrw+7jcZodpmpXJjefnO15M8UexIi6JR2E5thyvsmHyhL6ZDDMUNR4bKJPd4g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@capsizecss/unpack": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-4.0.1.tgz", + "integrity": "sha512-CuNiSqg7+e1cO/GjffyMOm5Tt2jUF9CWHHnvQ/UkqvtkGfHdgwEC0wpmq7fkN3gxwpRnrAN0WzO3vREKmNolMQ==", + "license": "MIT", + "dependencies": { + "fontkitten": "^1.0.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@clack/core": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@clack/core/-/core-1.4.3.tgz", + "integrity": "sha512-/kr3UWNtdJfxZtPgDqUOmG2pvwlmcLGheex5yiZKdwbzZJxhV+HMNR9QNmyY5cGwTNV6LrR7Jtp+KjhUAP1qBQ==", + "license": "MIT", + "dependencies": { + "fast-wrap-ansi": "^0.2.0", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 20.12.0" + } + }, + "node_modules/@clack/prompts": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-1.7.0.tgz", + "integrity": "sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A==", + "license": "MIT", + "dependencies": { + "@clack/core": "1.4.3", + "fast-string-width": "^3.0.2", + "fast-wrap-ansi": "^0.2.0", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 20.12.0" + } + }, + "node_modules/@ctrl/tinycolor": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-4.2.0.tgz", + "integrity": "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/@emnapi/core": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.3.tgz", + "integrity": "sha512-zLpS5asjEb7lq8jYLq37N6XKaE41DIexlY1rF/z4/tIl3wo13Sqm28fRyfIsKZD+NZ8mM5RoKkpW/rBcuoSZSg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.3", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.3.tgz", + "integrity": "sha512-ELEBe8PsLvvJ6QMr0zLt8ffvOHW/dc1m3CEzNMg7aJUv3bMaoDtw2TXyDAwkYBuroxxuHEwhRTLJSe5sya547g==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@expressive-code/core": { + "version": "0.44.1", + "resolved": "https://registry.npmjs.org/@expressive-code/core/-/core-0.44.1.tgz", + "integrity": "sha512-3dDo9N8D7hYrLNNMMWFovg3+aDUtnQm7c7z0GZc1c0LEFVBc0Q6lKG+tVT28gDadOvsgOANfCn35fgpe97Pmgg==", + "license": "MIT", + "dependencies": { + "@ctrl/tinycolor": "^4.0.4", + "hast-util-select": "^6.0.2", + "hast-util-to-html": "^9.0.1", + "hast-util-to-text": "^4.0.1", + "hastscript": "^9.0.0", + "postcss": "^8.4.38", + "postcss-nested": "^6.0.1", + "unist-util-visit": "^5.0.0", + "unist-util-visit-parents": "^6.0.1" + } + }, + "node_modules/@expressive-code/plugin-frames": { + "version": "0.44.1", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-frames/-/plugin-frames-0.44.1.tgz", + "integrity": "sha512-HC/bdRao9225ApcgO/e3jn8ZOhldKO7ob1O/Tcipvtv7Vb5nMphZhMtD9uuywpvxkPYBHJi3504WhrKg05Dwqg==", + "license": "MIT", + "dependencies": { + "@expressive-code/core": "^0.44.1" + } + }, + "node_modules/@expressive-code/plugin-shiki": { + "version": "0.44.1", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-shiki/-/plugin-shiki-0.44.1.tgz", + "integrity": "sha512-YApiZt3buUzBwL5tqj8G+sYC5NjMjRCHgQwr9bmGl69rtcHy6fE9dooWUeKYB978fJT2BuxT5FeHcF47rA3SEg==", + "license": "MIT", + "dependencies": { + "@expressive-code/core": "^0.44.1", + "shiki": "^4.0.2" + } + }, + "node_modules/@expressive-code/plugin-text-markers": { + "version": "0.44.1", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-text-markers/-/plugin-text-markers-0.44.1.tgz", + "integrity": "sha512-B3BsJoJ8CFMlcIX9f+X9tcI3C4zPDO601+YuLi9GheSTNro7ZfqSjLptMQKBHOWZvxnAtY5zvIX7iO/qtBhNBg==", + "license": "MIT", + "dependencies": { + "@expressive-code/core": "^0.44.1" + } + }, + "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", + "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" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.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" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.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" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.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" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.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" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.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" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.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" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.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" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.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" + ], + "libc": [ + "glibc" + ], + "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" + ], + "libc": [ + "glibc" + ], + "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" + ], + "libc": [ + "glibc" + ], + "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" + ], + "libc": [ + "glibc" + ], + "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" + ], + "libc": [ + "glibc" + ], + "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" + ], + "libc": [ + "glibc" + ], + "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" + ], + "libc": [ + "musl" + ], + "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" + ], + "libc": [ + "musl" + ], + "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/@napi-rs/wasm-runtime": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz", + "integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "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/@oxc-project/types": { + "version": "0.139.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.139.0.tgz", + "integrity": "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@pagefind/darwin-arm64": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/darwin-arm64/-/darwin-arm64-1.5.2.tgz", + "integrity": "sha512-MXpI+7HsAdPkvJ0gk9xj9g541BCqBZOBbdwj9g6lB5LCj6kSV6nqDSjzcAJwvOsfu0fjwvC8hQU+ecfhp+MpiQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@pagefind/darwin-x64": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/darwin-x64/-/darwin-x64-1.5.2.tgz", + "integrity": "sha512-IojxFWMEJe0RQ7PQ3KXQsPIImNsbpPYpoZ+QUDrL8fAl/O27IX+LVLs74/UzEZy5uA2LD8Nz1AiwKr72vrkZQw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@pagefind/default-ui": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/default-ui/-/default-ui-1.5.2.tgz", + "integrity": "sha512-pm1LMnQg8N2B3n2TnjKlhaFihpz6zTiA4HiGQ6/slKO/+8K9CAU5kcjdSSPgpuk1PMuuN4hxLipUIifnrkl3Sg==", + "license": "MIT" + }, + "node_modules/@pagefind/freebsd-x64": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/freebsd-x64/-/freebsd-x64-1.5.2.tgz", + "integrity": "sha512-7EVzo9+0w+2cbe671BtMj10UlNo83I+HrLVLfRxO731svHRJKUfJ/mo05gU14pe9PCfpKNQT8FS3Xc/oDN6pOA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@pagefind/linux-arm64": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/linux-arm64/-/linux-arm64-1.5.2.tgz", + "integrity": "sha512-Ovt9+K35sqzn8H3ZMXGwls4TD/wMJuvRtShHIsmUQREmaxjrDEX7gHckRCrwYJ4XE1H1p6HkLz3wukrAnsfXQw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@pagefind/linux-x64": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/linux-x64/-/linux-x64-1.5.2.tgz", + "integrity": "sha512-V+tFqHKXhQKq/WqPBD67AFy7scn1/aZID00ws4fSDd+1daSi5UHR9VVlRrOUYKxn3VuFQYRD7lYXdZK1WED1YA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@pagefind/windows-arm64": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/windows-arm64/-/windows-arm64-1.5.2.tgz", + "integrity": "sha512-hN9Nh90fNW61nNRCW9ZyQrAj/mD0eRvmJ8NlTUzkbuW8kIzGJUi3cxjFkEcMZ5h/8FsKWD/VcouZl4yo1F7B6g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@pagefind/windows-x64": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/windows-x64/-/windows-x64-1.5.2.tgz", + "integrity": "sha512-Fa2Iyw7kaDRzGMfNYNUXNW2zbL5FQVDgSOcbDHdzBrDEdpqOqg8TcZ68F22ol6NJ9IGzvUdmeyZypLW5dyhqsg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz", + "integrity": "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz", + "integrity": "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz", + "integrity": "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz", + "integrity": "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz", + "integrity": "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz", + "integrity": "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz", + "integrity": "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz", + "integrity": "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz", + "integrity": "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz", + "integrity": "sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.5.tgz", + "integrity": "sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz", + "integrity": "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz", + "integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.11.1", + "@emnapi/runtime": "1.11.1", + "@napi-rs/wasm-runtime": "^1.1.6" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", + "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", + "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", + "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz", + "integrity": "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz", + "integrity": "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "license": "MIT" + }, + "node_modules/@rollup/pluginutils": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.4.0.tgz", + "integrity": "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==", + "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/@shikijs/core": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.3.1.tgz", + "integrity": "sha512-ANMDxuaPsNMdDC1m4vfvhlDmJweMwkE5XitTwrq2rWHx5jM+dlm4MmHt2PP6t0uejfR77SuhrhJ0zEijIF/uhA==", + "license": "MIT", + "dependencies": { + "@shikijs/primitive": "4.3.1", + "@shikijs/types": "4.3.1", + "@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.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.3.1.tgz", + "integrity": "sha512-JBItcnPuYq7jVJdZo/vMj94r+szT7XEjHFX+mvFDGSEIbVAXAGyHAHzhbWzpGOwYidCZrErJLLgn2PVeiokHnQ==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.3.1", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^4.3.6" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.3.1.tgz", + "integrity": "sha512-OXyNMzg0pews+msMj4cHeqT4xiYKKvbnn6VbdAXxfoFl3SSx4fJTc8FadECuc5/H9p3BzhNAoAUXKwAu9rWYhg==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.3.1", + "@shikijs/vscode-textmate": "^10.0.2" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/langs": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.3.1.tgz", + "integrity": "sha512-m0l9nsDqgBHvbZbk7A0/kXz/impK3uB/c6rAn6Gpg/uPtdZRQ+alsN/17MU5thb68XTj/4DxkZAotrM0GGSpDQ==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.3.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/primitive": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.3.1.tgz", + "integrity": "sha512-CXQRQOYy1leqQ8ceTeJdmXv/bsUY++6QyLpXJ94LZAAYj5X2SKRdc5ipguv4NPyGVKItB2PPwUpRNe0Sjh5S1A==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.3.1", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/themes": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.3.1.tgz", + "integrity": "sha512-dgpoJ4WqNi2yTmizQHBJ5zcX6j2lE6icN/0yt4l1kkf16jrY/pwPLoTb1ETsWMz0OBLf9ZNvwmxft+cH+N9qSA==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.3.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/types": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.3.1.tgz", + "integrity": "sha512-CHFxE0jztBIZRHH6gxXE7DXUCFXjReEGxZ/j0rfSLGKZuwp2xBYycEP14875DSa9KLL/6700oxIq6oO6ef9K2g==", + "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/@tybys/wasm-util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/debug": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "license": "MIT" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.5.tgz", + "integrity": "sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/js-yaml": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", + "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", + "license": "MIT" + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdx": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.14.tgz", + "integrity": "sha512-T48PeuJtvLosNTPVhfnIp3i/n3a4g4Bad7YCq5k64D4u7NwDrAotikQ+5+sjtUvBmxCMlbo3dVL+C2dP0rWHzg==", + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/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/node": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz", + "integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.18.0" + } + }, + "node_modules/@types/sax": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz", + "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "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.3", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.3.tgz", + "integrity": "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==", + "license": "ISC" + }, + "node_modules/acorn": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", + "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/am-i-vibing": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/am-i-vibing/-/am-i-vibing-0.4.0.tgz", + "integrity": "sha512-MxT4XZL7pzLHpuvhDKdMaQHMGGkJDLluKBLsbstn+8wv9sWcFT6h+0ve9qkml95amVTZtZV83gQe2hY+ojgHLg==", + "license": "MIT", + "dependencies": { + "process-ancestry": "^0.1.0" + }, + "bin": { + "am-i-vibing": "dist/cli.mjs" + } + }, + "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/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" + }, + "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": "7.1.3", + "resolved": "https://registry.npmjs.org/astro/-/astro-7.1.3.tgz", + "integrity": "sha512-4dhPyAAXthf3xLEYnG8SeL7yr/nTPPABfY7e9YF0yuO+vK9Xp+8Q5j4xzsmL3GueukQv4oNwGNTBepLOiDGeJA==", + "license": "MIT", + "dependencies": { + "@astrojs/compiler-rs": "^0.3.1", + "@astrojs/internal-helpers": "0.10.1", + "@astrojs/markdown-satteri": "0.3.4", + "@astrojs/telemetry": "3.3.3", + "@capsizecss/unpack": "^4.0.0", + "@clack/prompts": "^1.1.0", + "@oslojs/encoding": "^1.1.0", + "@rollup/pluginutils": "^5.3.0", + "am-i-vibing": "^0.4.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": "^2.0.1", + "devalue": "^5.8.1", + "diff": "^8.0.3", + "dset": "^3.1.4", + "es-module-lexer": "^2.0.0", + "esbuild": "^0.28.0", + "flattie": "^1.1.1", + "fontace": "~0.4.1", + "get-tsconfig": "5.0.0-beta.4", + "github-slugger": "^2.0.0", + "html-escaper": "3.0.3", + "http-cache-semantics": "^4.2.0", + "js-yaml": "^4.1.1", + "jsonc-parser": "^3.3.1", + "magic-string": "^0.30.21", + "magicast": "^0.5.2", + "mrmime": "^2.0.1", + "neotraverse": "^1.0.1", + "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.4", + "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", + "ultrahtml": "^1.6.0", + "unifont": "~0.7.4", + "unstorage": "^1.17.5", + "vite": "^8.0.13", + "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 || ^0.35.0" + }, + "peerDependencies": { + "@astrojs/markdown-remark": "7.2.1" + }, + "peerDependenciesMeta": { + "@astrojs/markdown-remark": { + "optional": true + } + } + }, + "node_modules/astro-expressive-code": { + "version": "0.44.1", + "resolved": "https://registry.npmjs.org/astro-expressive-code/-/astro-expressive-code-0.44.1.tgz", + "integrity": "sha512-DT1LnCqbHasBKlvzJ3m6LR4VI94wwx3W9EV/YbP1te4rqjOHsvsezHYuqb5MeLWLftXms/1FA9QBbwCo43DnJQ==", + "license": "MIT", + "dependencies": { + "rehype-expressive-code": "^0.44.1", + "url-extras": "^0.1.0" + }, + "peerDependencies": { + "astro": "^4.0.0-beta || ^5.0.0-beta || ^3.3.0 || ^6.0.0-beta || ^7.0.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/bcp-47": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bcp-47/-/bcp-47-2.1.1.tgz", + "integrity": "sha512-KLw+H/gd2p4zly1X7Yh/qziuyae5/w/QFnvTng9eZL5fvszL7Whl3MBoWF8yxL7ksUjBfOD+OxkytiqbBpG+Fw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/bcp-47-match": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.3.tgz", + "integrity": "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==", + "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": "2.0.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-2.0.1.tgz", + "integrity": "sha512-yuToqVvRrj6pfDXREyQAAv8SkAEk/8GS3jQRTiUMm66TVtBYmqQeoEjL2Lmq8Rpo6271vH76InTChTitEAm65w==", + "license": "MIT", + "engines": { + "node": ">=22" + }, + "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-selector-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-3.3.0.tgz", + "integrity": "sha512-Y2asgMGFqJKF4fq4xHDSlFYIkeVfRsm69lQC1q9kbEsH5XtnINTMrweLkjYMeaUgiXBy/uvKeO/a1JHTNnmB2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" + }, + "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/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "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", + "engines": { + "node": ">=8" + } + }, + "node_modules/devalue": { + "version": "5.8.2", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.8.2.tgz", + "integrity": "sha512-DObPPAfdtFbXjxLqK8s2Xk9ZuWz5+ZoFEhC7J76es4GU/rEiXwHTmbImoCdyoCOcBH1UF3+Cz6Z2sYD4hyl5TA==", + "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/direction": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/direction/-/direction-2.0.1.tgz", + "integrity": "sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==", + "license": "MIT", + "bin": { + "direction": "cli.js" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "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.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz", + "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==", + "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.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + } + }, + "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/expressive-code": { + "version": "0.44.1", + "resolved": "https://registry.npmjs.org/expressive-code/-/expressive-code-0.44.1.tgz", + "integrity": "sha512-GakidxhapWDzpKLqEaFQ8wGk6gAqEtPQibu8+yPBfnDLgev5Vdsh1pasTxnrXL/mzIknyqeTwhMHTghdaiUrTg==", + "license": "MIT", + "dependencies": { + "@expressive-code/core": "^0.44.1", + "@expressive-code/plugin-frames": "^0.44.1", + "@expressive-code/plugin-shiki": "^0.44.1", + "@expressive-code/plugin-text-markers": "^0.44.1" + } + }, + "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": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-string-truncated-width/-/fast-string-truncated-width-3.0.3.tgz", + "integrity": "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==", + "license": "MIT" + }, + "node_modules/fast-string-width": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-string-width/-/fast-string-width-3.0.2.tgz", + "integrity": "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==", + "license": "MIT", + "dependencies": { + "fast-string-truncated-width": "^3.0.2" + } + }, + "node_modules/fast-wrap-ansi": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/fast-wrap-ansi/-/fast-wrap-ansi-0.2.2.tgz", + "integrity": "sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==", + "license": "MIT", + "dependencies": { + "fast-string-width": "^3.0.2" + } + }, + "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/get-tsconfig": { + "version": "5.0.0-beta.4", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-5.0.0-beta.4.tgz", + "integrity": "sha512-7nF7C9fIPFEMHgEMEfgIlO9wDdZ8CyHw27rWciFZfHvHDReIiPhsYuzPRXsfvBCqFy1l8RRyyWV7QLM+ZhUJsQ==", + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "engines": { + "node": ">=20.20.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "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-embedded": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-embedded/-/hast-util-embedded-3.0.0.tgz", + "integrity": "sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-is-element": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-format": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hast-util-format/-/hast-util-format-1.1.0.tgz", + "integrity": "sha512-yY1UDz6bC9rDvCWHpx12aIBGRG7krurX0p0Fm6pT547LwDIZZiNr8a+IHDogorAdreULSEzP82Nlv5SZkHZcjA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-minify-whitespace": "^1.0.0", + "hast-util-phrasing": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "html-whitespace-sensitive-tag-names": "^3.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-html": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", + "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.1.0", + "hast-util-from-parse5": "^8.0.0", + "parse5": "^7.0.0", + "vfile": "^6.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-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-has-property": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-3.0.0.tgz", + "integrity": "sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-body-ok-link": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-is-body-ok-link/-/hast-util-is-body-ok-link-3.0.1.tgz", + "integrity": "sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.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-minify-whitespace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hast-util-minify-whitespace/-/hast-util-minify-whitespace-1.0.1.tgz", + "integrity": "sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "unist-util-is": "^6.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-phrasing": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-phrasing/-/hast-util-phrasing-3.0.1.tgz", + "integrity": "sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-has-property": "^3.0.0", + "hast-util-is-body-ok-link": "^3.0.0", + "hast-util-is-element": "^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-select": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/hast-util-select/-/hast-util-select-6.0.4.tgz", + "integrity": "sha512-RqGS1ZgI0MwxLaKLDxjprynNzINEkRHY2i8ln4DDjgv9ZhcYVIHN9rlpiYsqtFwrgpYU361SyWDQcGNIBVu3lw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "bcp-47-match": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "css-selector-parser": "^3.0.0", + "devlop": "^1.0.0", + "direction": "^2.0.0", + "hast-util-has-property": "^3.0.0", + "hast-util-to-string": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "nth-check": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "unist-util-visit": "^5.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-string": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.1.tgz", + "integrity": "sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.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/html-whitespace-sensitive-tag-names": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-whitespace-sensitive-tag-names/-/html-whitespace-sensitive-tag-names-3.0.1.tgz", + "integrity": "sha512-q+310vW8zmymYHALr1da4HyXUQ0zgiIwIicEfotYPWGN0OJVEN/58IJ3A4GBYcEq3LGAZqKb+ugvP0GNB9CEAA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "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/i18next": { + "version": "26.3.6", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-26.3.6.tgz", + "integrity": "sha512-Bu5Z2nAXgfVyM8xvW3jk9EKRIuX37PudsrBViThNFx7CR7aaYTpP01cxNB/E4c4UUzTDiAZRstEhsRfPOL/8xA==", + "funding": [ + { + "type": "individual", + "url": "https://www.locize.com/i18next" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + }, + { + "type": "individual", + "url": "https://www.locize.com" + } + ], + "license": "MIT", + "peerDependencies": { + "typescript": "^5 || ^6 || ^7" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "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-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/js-yaml": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", + "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "license": "MIT" + }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/lightningcss": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.33.0", + "lightningcss-darwin-arm64": "1.33.0", + "lightningcss-darwin-x64": "1.33.0", + "lightningcss-freebsd-x64": "1.33.0", + "lightningcss-linux-arm-gnueabihf": "1.33.0", + "lightningcss-linux-arm64-gnu": "1.33.0", + "lightningcss-linux-arm64-musl": "1.33.0", + "lightningcss-linux-x64-gnu": "1.33.0", + "lightningcss-linux-x64-musl": "1.33.0", + "lightningcss-win32-arm64-msvc": "1.33.0", + "lightningcss-win32-x64-msvc": "1.33.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "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.3", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.3.tgz", + "integrity": "sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.3", + "@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-directive": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.1.0.tgz", + "integrity": "sha512-I3fNFt+DHmpWCYAT7quoM6lHf9wuqtI+oCOfvILnoicNIqjh5E3dEJWiXuYME2gNe8vl1iMQwyUHa7bgFmak6Q==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.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-visit-parents": "^6.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-directive": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-4.0.0.tgz", + "integrity": "sha512-/C2nqVmXXmiseSSuCdItCMho7ybwwop6RrrRPk0KbOHW21JKoCldC+8rFOaundDoRBUWBnJJcxeA/Kvi34WQXg==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "parse-entities": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "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.16", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", + "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", + "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": "1.0.1", + "resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-1.0.1.tgz", + "integrity": "sha512-WmmLty1YWwJl9yZi77v2dVIV6X2kuYV8YYBI/G3LWGKdGHmHUvL1z7FW0iDvEvGAwNEoc5x1tOOOyDnf5jJw/w==", + "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.4", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", + "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "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.2", + "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.2.tgz", + "integrity": "sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==", + "license": "MIT" + }, + "node_modules/oniguruma-to-es": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.6.tgz", + "integrity": "sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==", + "license": "MIT", + "dependencies": { + "oniguruma-parser": "^0.12.2", + "regex": "^6.1.0", + "regex-recursion": "^6.0.2" + } + }, + "node_modules/p-limit": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-7.3.1.tgz", + "integrity": "sha512-0trZaiG7Y7kN/Egy9a8j47t9osC0Tch4PaIWd9yGF6bvmlk7muExRvGNYb8sXBwEKMoNKsbNN9P8EefuQekE4Q==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.2.1" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-queue": { + "version": "9.3.3", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.3.3.tgz", + "integrity": "sha512-NXAOdnEe5FsZJfT4oK84lE1Y5cFFdWlRuOo5tww8DyNMxyRXwn39fIkUtNLKppcPC+UYU/bXujNCUGDv01y7CA==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^5.0.4", + "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.8.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.8.0.tgz", + "integrity": "sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==", + "license": "MIT" + }, + "node_modules/pagefind": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/pagefind/-/pagefind-1.5.2.tgz", + "integrity": "sha512-XTUaK0hXMCu2jszWE584JGQT7y284TmMV9l/HX3rnG5uo3rHI/uHU56XTyyyPFjeWEBxECbAi0CaFDJOONtG0Q==", + "license": "MIT", + "bin": { + "pagefind": "lib/runner/bin.cjs" + }, + "optionalDependencies": { + "@pagefind/darwin-arm64": "1.5.2", + "@pagefind/darwin-x64": "1.5.2", + "@pagefind/freebsd-x64": "1.5.2", + "@pagefind/linux-arm64": "1.5.2", + "@pagefind/linux-x64": "1.5.2", + "@pagefind/windows-arm64": "1.5.2", + "@pagefind/windows-x64": "1.5.2" + } + }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, + "node_modules/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.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz", + "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.16", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.4.tgz", + "integrity": "sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "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/process-ancestry": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/process-ancestry/-/process-ancestry-0.1.0.tgz", + "integrity": "sha512-tGqJW/UnclpYASFcM6Xh8D8l/BMtaQ9+CSG0vlJSJTcdMM4lDRv4c6H0Pdcsfted+bVczdYSfk2fdukg2gQkZg==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/property-information": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.2.0.tgz", + "integrity": "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/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-expressive-code": { + "version": "0.44.1", + "resolved": "https://registry.npmjs.org/rehype-expressive-code/-/rehype-expressive-code-0.44.1.tgz", + "integrity": "sha512-+VZgs7Evw4LXRN3owpoBNSTpYuW6GeOdjqcUT1TuY8o/4MGPtbd0EU7Bgrju7X8KrQ6SslOBAuGWJ5fV5TriJQ==", + "license": "MIT", + "dependencies": { + "expressive-code": "^0.44.1" + } + }, + "node_modules/rehype-format": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/rehype-format/-/rehype-format-5.0.1.tgz", + "integrity": "sha512-zvmVru9uB0josBVpr946OR8ui7nJEdzZobwLOOqHb/OOD88W0Vk2SqLwoVOj0fM6IPCCO6TaV9CvQvJMWwukFQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-format": "^1.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-directive": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-4.0.0.tgz", + "integrity": "sha512-7sxn4RfF1o3izevPV1DheyGDD6X4c9hrGpfdUpm7uC++dqrnJxIZVkk7CoKqcLm0VUMAuOol7Mno3m6g8cfMuA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-directive": "^3.0.0", + "micromark-extension-directive": "^4.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.3", + "resolved": "https://registry.npmjs.org/remark-smartypants/-/remark-smartypants-3.0.3.tgz", + "integrity": "sha512-gCaK+ndZ0hYezlqFegHFCVh2CQemsi0Npdh1qVM9bxlUFknjkbP6VmojWhddOCrbK0PbbacmYLWfTULRiT1eWA==", + "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/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "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/rolldown": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz", + "integrity": "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==", + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.139.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.1.5", + "@rolldown/binding-darwin-arm64": "1.1.5", + "@rolldown/binding-darwin-x64": "1.1.5", + "@rolldown/binding-freebsd-x64": "1.1.5", + "@rolldown/binding-linux-arm-gnueabihf": "1.1.5", + "@rolldown/binding-linux-arm64-gnu": "1.1.5", + "@rolldown/binding-linux-arm64-musl": "1.1.5", + "@rolldown/binding-linux-ppc64-gnu": "1.1.5", + "@rolldown/binding-linux-s390x-gnu": "1.1.5", + "@rolldown/binding-linux-x64-gnu": "1.1.5", + "@rolldown/binding-linux-x64-musl": "1.1.5", + "@rolldown/binding-openharmony-arm64": "1.1.5", + "@rolldown/binding-wasm32-wasi": "1.1.5", + "@rolldown/binding-win32-arm64-msvc": "1.1.5", + "@rolldown/binding-win32-x64-msvc": "1.1.5" + } + }, + "node_modules/satteri": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/satteri/-/satteri-0.9.5.tgz", + "integrity": "sha512-ZuWVl+vnM64y+/TtX8Kosv2c00W+hLQiiwnEL6H0UKVVrxFqMw4D2CJHHQaouVd89OAhtBBfjWLqhKi3TVUV4w==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.5", + "@types/hast": "^3.0.4", + "@types/mdast": "^4.0.4", + "@types/unist": "^3.0.3" + }, + "optionalDependencies": { + "@bruits/satteri-darwin-arm64": "0.9.5", + "@bruits/satteri-darwin-x64": "0.9.5", + "@bruits/satteri-linux-arm64-gnu": "0.9.5", + "@bruits/satteri-linux-arm64-musl": "0.9.5", + "@bruits/satteri-linux-x64-gnu": "0.9.5", + "@bruits/satteri-linux-x64-musl": "0.9.5", + "@bruits/satteri-wasm32-wasi": "0.9.5", + "@bruits/satteri-win32-arm64-msvc": "0.9.5", + "@bruits/satteri-win32-x64-msvc": "0.9.5" + } + }, + "node_modules/sax": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.1.tgz", + "integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "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", + "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.3.1", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.3.1.tgz", + "integrity": "sha512-oR+qDVi2OjX1tmDpyv+3KviX01KzO6Af+0NNnKnsp9491UEGz2YpxTuJboS/6VhYpTdqzmuJBuiTlrAWWJAssw==", + "license": "MIT", + "dependencies": { + "@shikijs/core": "4.3.1", + "@shikijs/engine-javascript": "4.3.1", + "@shikijs/engine-oniguruma": "4.3.1", + "@shikijs/langs": "4.3.1", + "@shikijs/themes": "4.3.1", + "@shikijs/types": "4.3.1", + "@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/sitemap": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-9.0.1.tgz", + "integrity": "sha512-S6hzjGJSG3d6if0YoF5kTyeRJvia6FSTBroE5fQ0bu1QNxyJqhhinfUsXi9fH3MgtXODWvwo2BDyQSnhPQ88uQ==", + "license": "MIT", + "dependencies": { + "@types/node": "^24.9.2", + "@types/sax": "^1.2.1", + "arg": "^5.0.0", + "sax": "^1.4.1" + }, + "bin": { + "sitemap": "dist/esm/cli.js" + }, + "engines": { + "node": ">=20.19.5", + "npm": ">=10.8.2" + } + }, + "node_modules/smol-toml": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.7.0.tgz", + "integrity": "sha512-aqVvWoyO21L23mb+drl4RmMXbf6N7FdHjAhTRA9ZBL7apWBgfWC16KjrASI+1p9GAroljyMHj6fK67i0UiTNvQ==", + "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/stream-replace-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stream-replace-string/-/stream-replace-string-2.0.0.tgz", + "integrity": "sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==", + "license": "MIT" + }, + "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.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.2.tgz", + "integrity": "sha512-ekx94z1rRc5LDi6oSUaeRnYhd0UOJxdtQCL2rF8xpWxD3TPAsISWOrxezqGovqS38GRZOdpDfvQe3ts6F7nsng==", + "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.15", + "resolved": "https://registry.npmjs.org/tinyclip/-/tinyclip-0.1.15.tgz", + "integrity": "sha512-uo33abH+Ays0xYaDysoBt494Hb3hsEczMpcC0MwFl773pazORx4fmvKhclhR1wonUbB6vvpRsvVMwnhfqeMc+A==", + "license": "MIT", + "engines": { + "node": "^16.14.0 || >= 17.3.0" + } + }, + "node_modules/tinyexec": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", + "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/ufo": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz", + "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==", + "license": "MIT" + }, + "node_modules/ultrahtml": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.7.0.tgz", + "integrity": "sha512-2xRd0VHoAQE4M+vF/DvFFB7pUV0ZxTW1TLi7lHQWnF/Sb5TPeEUV/l+hxcNnGO00ZXGnR0voCMmYRKQf+rvJ2g==", + "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/undici-types": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "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/url-extras": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/url-extras/-/url-extras-0.1.0.tgz", + "integrity": "sha512-8tzwTeXFPuX/5PHuCDQE5Dd9Ts4rwoq2t9aIT+HS4iAVpmj5l4Ao7Q+BuuFjvWRqrLswBhQDk8O96ZicgCqQqw==", + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "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": "8.1.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.5.tgz", + "integrity": "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==", + "license": "MIT", + "dependencies": { + "lightningcss": "^1.32.0", + "picomatch": "^4.0.5", + "postcss": "^8.5.17", + "rolldown": "~1.1.5", + "tinyglobby": "^0.2.17" + }, + "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", + "@vitejs/devtools": "^0.3.0", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.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 + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "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/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.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/docs/site/package.json b/docs/site/package.json new file mode 100644 index 0000000..9139593 --- /dev/null +++ b/docs/site/package.json @@ -0,0 +1,17 @@ +{ + "name": "site", + "type": "module", + "version": "0.0.1", + "scripts": { + "dev": "astro dev", + "start": "astro dev", + "build": "astro build", + "preview": "astro preview", + "astro": "astro" + }, + "dependencies": { + "@astrojs/starlight": "^0.41.4", + "astro": "^7.0.2", + "sharp": "^0.34.5" + } +} \ No newline at end of file diff --git a/docs/site/public/favicon.svg b/docs/site/public/favicon.svg new file mode 100644 index 0000000..cba5ac1 --- /dev/null +++ b/docs/site/public/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/site/src/assets/houston.webp b/docs/site/src/assets/houston.webp new file mode 100644 index 0000000000000000000000000000000000000000..930c164974ad8eb528878f15a98016249b8cf546 GIT binary patch literal 98506 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 b6~t;_wBcJ3AWgga7~Sz~izoKbpAY~5r|m$8 literal 0 HcmV?d00001 diff --git a/docs/site/src/content.config.ts b/docs/site/src/content.config.ts new file mode 100644 index 0000000..6289a4b --- /dev/null +++ b/docs/site/src/content.config.ts @@ -0,0 +1,25 @@ +import { defineCollection } from 'astro:content'; +import { z } from 'astro/zod'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ + loader: docsLoader(), + schema: docsSchema({ + // z.strictObject (not z.object) so that Zod v4's default key-stripping + // doesn't silently swallow typos in generated frontmatter — an unknown + // key like `bogusField` must fail the build, not disappear quietly. + extend: z.strictObject({ + // Include this page in the generated man page. + man: z.boolean().default(true), + // Publish this page to the website. + site: z.boolean().default(true), + // Verbatim heading text used by the man page renderer. + manTitle: z.string().optional(), + // Keywords resolving to this page via `help config `. + helpKeywords: z.array(z.string()).default([]), + }), + }), + }), +}; diff --git a/docs/site/tsconfig.json b/docs/site/tsconfig.json new file mode 100644 index 0000000..8bf91d3 --- /dev/null +++ b/docs/site/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "astro/tsconfigs/strict", + "include": [".astro/types.d.ts", "**/*"], + "exclude": ["dist"] +} -- 2.52.0 From a4054de4f60bcd28da4c5303c2193fc727e5b867 Mon Sep 17 00:00:00 2001 From: rootiest Date: Sat, 25 Jul 2026 22:44:28 -0400 Subject: [PATCH 10/15] feat(docs): generate Starlight content from the manual tree Add build_manual.build_site(), which walks docs/manual and emits the Astro Starlight content collection: plain pages copied with pipeline-only frontmatter (man/site/manTitle/helpKeywords) stripped, and *-functions/ category files exploded into one page per function plus a CardGrid/LinkCard overview. Writes src/sidebar.json for astro.config.mjs to import. Wires --site alongside the existing --concat flag. Fixes two latent defects found while building the real site against the strict content.config.ts schema: - _split_entries now tracks fenced code blocks (like manualtools.shift_headings does) so a `## ` inside a fence can't be mistaken for an entry boundary. - LinkCard title/description are escaped for JSX attribute context, since shell synopses routinely contain `` angle brackets that would otherwise open unterminated MDX/JSX parsing. Also fixes the generated sidebar shape for the functions category: Starlight 0.39+ dropped support for a bare `autogenerate` sibling of `label` on a top-level group, so the autogenerate config now nests inside `items`. Verified with a full `astro build` (temporarily pointing astro.config.mjs at the generated sidebar.json, then reverted since replacing that config is a later task's deliverable): 120 pages built cleanly, no content-collection/frontmatter/MDX errors. --- docs/build-manual.py | 176 ++++++++++++++++++++++++++++++++++++++++-- docs/verify-manual.py | 21 +++++ 2 files changed, 189 insertions(+), 8 deletions(-) diff --git a/docs/build-manual.py b/docs/build-manual.py index c62d7b3..19dc7e6 100644 --- a/docs/build-manual.py +++ b/docs/build-manual.py @@ -8,6 +8,9 @@ """ import argparse +import json +import re +import shutil import sys from pathlib import Path @@ -45,21 +48,178 @@ def build_concat(root: Path) -> str: return "\n\n".join(chunks) + "\n" +SENTENCE_RE = re.compile(r"^(.+?[.!?])(\s|$)", re.S) +PIPELINE_KEYS = ("man", "site", "manTitle", "helpKeywords") +JSX_ATTR_ESCAPES = ( + ("&", "&"), + ('"', """), + ("<", "<"), + ("{", "{"), +) + + +def _jsx_attr_escape(value: str) -> str: + """Escape a string for safe use inside a quoted JSX attribute value. + + `&` must go first so escaping later characters doesn't double-escape + the ampersands it introduces. `"` closes the attribute early; `<` and + `{` are otherwise-live MDX/JSX syntax that must not be interpreted. + """ + for char, escape in JSX_ATTR_ESCAPES: + value = value.replace(char, escape) + return value + + +def _first_sentence(body: str) -> str: + """Extract a one-line description from the start of an entry body.""" + for line in body.split("\n"): + line = line.strip() + if not line or line.startswith(("#", "```", "|", "-", "*", ">")): + continue + m = SENTENCE_RE.match(line) + return (m.group(1) if m else line)[:160] + return "" + + +def _page_fm(fm: dict) -> dict: + """Strip pipeline-only keys from frontmatter destined for the site.""" + return {k: v for k, v in fm.items() if k not in PIPELINE_KEYS} + + +def _split_entries(body: str) -> tuple[str, list[tuple[str, str]]]: + """Split a category body into (intro, [(entry title, entry body)]). + + Fence-aware: an H2-looking line (`## ...`) inside a fenced code block + (tracked the same way as `manualtools.shift_headings`) is treated as + ordinary body text, not an entry boundary. + """ + lines = body.split("\n") + heading_re = re.compile(r"^## (.+)$") + boundaries: list[tuple[int, str]] = [] + in_fence = False + for i, line in enumerate(lines): + if mt.FENCE_RE.match(line): + in_fence = not in_fence + continue + if not in_fence: + m = heading_re.match(line) + if m: + boundaries.append((i, m.group(1))) + + if not boundaries: + return body.strip(), [] + + intro = "\n".join(lines[: boundaries[0][0]]).strip() + entries = [] + for idx, (line_no, title) in enumerate(boundaries): + start = line_no + 1 + end = boundaries[idx + 1][0] if idx + 1 < len(boundaries) else len(lines) + entry_body = "\n".join(lines[start:end]).strip() + entries.append((title.strip(), entry_body)) + return intro, entries + + +def build_site(root: Path, out: Path) -> list[dict]: + """Write the Starlight content tree. Returns the sidebar structure.""" + if out.exists(): + shutil.rmtree(out) + out.mkdir(parents=True) + + sidebar: list[dict] = [] + for path, _depth in mt.walk(root): + fm, body = mt.parse(path) + if not fm.get("site", True): + continue + + rel = path.relative_to(root) + is_function_dir = rel.parts and rel.parts[0].endswith("-functions") + + if not is_function_dir: + target = out / rel + target.parent.mkdir(parents=True, exist_ok=True) + target.write_text(mt.serialize(_page_fm(fm), body)) + if rel.name != "index.md": + sidebar.append({"label": fm["title"], "link": "/" + rel.stem + "/"}) + continue + + # Section 5: category index page keeps its slot; entries explode. + slug_dir = "functions" + if rel.name == "index.md": + target = out / slug_dir / "index.md" + target.parent.mkdir(parents=True, exist_ok=True) + target.write_text(mt.serialize(_page_fm(fm), body)) + sidebar.append( + { + "label": fm["title"], + "collapsed": True, + # Starlight >=0.39 rejects a bare `autogenerate` sibling + # of `label` on a top-level group (removed in v0.39.0); + # the autogenerate config must be nested inside `items`. + "items": [{"autogenerate": {"directory": slug_dir}}], + } + ) + continue + + category = re.sub(r"^\d+-", "", rel.stem) + cat_dir = out / slug_dir / category + cat_dir.mkdir(parents=True, exist_ok=True) + intro, entries = _split_entries(body) + + cards = [] + for title, entry_body in entries: + entry_slug = re.sub(r"[^\w-]+", "-", title.strip().lower()).strip("-") + desc = _first_sentence(entry_body) + entry_fm = {"title": title} + if desc: + entry_fm["description"] = desc + (cat_dir / f"{entry_slug}.md").write_text( + mt.serialize(entry_fm, entry_body) + ) + href = f"/{slug_dir}/{category}/{entry_slug}/" + safe_title = _jsx_attr_escape(title) + safe_desc = _jsx_attr_escape(desc) + cards.append( + f' " + ) + + overview = ( + "import { CardGrid, LinkCard } from '@astrojs/starlight/components';\n\n" + + (f"{intro}\n\n" if intro else "") + + "\n" + + "\n".join(cards) + + "\n\n" + ) + (cat_dir / "index.mdx").write_text(mt.serialize(_page_fm(fm), overview)) + + return sidebar + + def main() -> int: ap = argparse.ArgumentParser(description=__doc__) ap.add_argument("--concat", action="store_true", help="emit the pandoc document") + ap.add_argument("--site", action="store_true", help="emit the Starlight content tree") ap.add_argument("-o", "--output", type=Path, help="write to PATH instead of stdout") args = ap.parse_args() - if not args.concat: - ap.error("nothing to do: pass --concat") + if not (args.concat or args.site): + ap.error("nothing to do: pass --concat and/or --site") - text = build_concat(MANUAL) - if args.output: - args.output.write_text(text) - print(f"wrote {args.output}") - else: - sys.stdout.write(text) + if args.site: + src = DOCS / "site" / "src" + out = src / "content" / "docs" + sidebar = build_site(MANUAL, out) + (src / "sidebar.json").write_text(json.dumps(sidebar, indent=2) + "\n") + print(f"wrote site content to {out} ({len(sidebar)} sidebar entries)") + + if args.concat: + text = build_concat(MANUAL) + if args.output: + args.output.write_text(text) + print(f"wrote {args.output}") + else: + sys.stdout.write(text) return 0 diff --git a/docs/verify-manual.py b/docs/verify-manual.py index 1339a7c..8f0f391 100644 --- a/docs/verify-manual.py +++ b/docs/verify-manual.py @@ -192,6 +192,27 @@ def test_every_index_keyword_resolves(): assert not missing, "unresolvable index keywords:\n " + "\n ".join(missing) +def test_site_build_produces_function_pages(): + import tempfile + + import build_manual + + docs = Path(__file__).parent + with tempfile.TemporaryDirectory() as d: + out = Path(d) + sidebar = build_manual.build_site(docs / "manual", out) + pages = list(out.rglob("*.md*")) + assert (out / "index.md").exists(), "landing page missing" + fn_pages = [p for p in pages if "functions" in p.parts and p.name != "index.mdx"] + assert len(fn_pages) > 80, f"expected >80 function pages, got {len(fn_pages)}" + assert not (out / "00-name.md").exists(), "site:false page was published" + assert sidebar, "sidebar structure is empty" + for page in pages: + fm, _ = mt.parse(page) + assert "manTitle" not in fm, f"{page.name} leaked manTitle into site output" + assert "title" in fm, f"{page.name} has no title" + + TESTS = [v for k, v in sorted(globals().items()) if k.startswith("test_")] -- 2.52.0 From 3bb534f20bdc6490846e1b3c987225d4e844a2f9 Mon Sep 17 00:00:00 2001 From: rootiest Date: Sat, 25 Jul 2026 22:59:11 -0400 Subject: [PATCH 11/15] feat(docs): configure Starlight site with Catppuccin theme --- docs/site/astro.config.mjs | 38 +++++++++++++---------------- docs/site/src/styles/catppuccin.css | 28 +++++++++++++++++++++ 2 files changed, 45 insertions(+), 21 deletions(-) create mode 100644 docs/site/src/styles/catppuccin.css diff --git a/docs/site/astro.config.mjs b/docs/site/astro.config.mjs index 69b83b3..195b237 100644 --- a/docs/site/astro.config.mjs +++ b/docs/site/astro.config.mjs @@ -1,26 +1,22 @@ -// @ts-check import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; +import sidebar from './src/sidebar.json' with { type: 'json' }; -// https://astro.build/config export default defineConfig({ - integrations: [ - starlight({ - title: 'My Docs', - social: [{ icon: 'github', label: 'GitHub', href: 'https://github.com/withastro/starlight' }], - sidebar: [ - { - label: 'Guides', - items: [ - // Each item here is one entry in the navigation menu. - { label: 'Example Guide', slug: 'guides/example' }, - ], - }, - { - label: 'Reference', - items: [{ autogenerate: { directory: 'reference' } }], - }, - ], - }), - ], + site: 'https://fish-config.pages.dev', + integrations: [ + starlight({ + title: 'Fish Config', + description: 'Reference manual for the rootiest fish configuration.', + social: [ + { + icon: 'code-branch', + label: 'Gitea', + href: 'https://git.rootiest.dev/rootiest/fish-config', + }, + ], + customCss: ['./src/styles/catppuccin.css'], + sidebar, + }), + ], }); diff --git a/docs/site/src/styles/catppuccin.css b/docs/site/src/styles/catppuccin.css new file mode 100644 index 0000000..7eaf590 --- /dev/null +++ b/docs/site/src/styles/catppuccin.css @@ -0,0 +1,28 @@ +/* Catppuccin Mocha (dark) / Latte (light) mapped onto Starlight tokens. */ +:root { + --sl-color-accent-low: #1e1e2e; + --sl-color-accent: #89b4fa; + --sl-color-accent-high: #b4befe; + --sl-color-white: #cdd6f4; + --sl-color-gray-1: #bac2de; + --sl-color-gray-2: #a6adc8; + --sl-color-gray-3: #7f849c; + --sl-color-gray-4: #585b70; + --sl-color-gray-5: #45475a; + --sl-color-gray-6: #313244; + --sl-color-black: #181825; +} + +:root[data-theme='light'] { + --sl-color-accent-low: #dce0e8; + --sl-color-accent: #1e66f5; + --sl-color-accent-high: #7287fd; + --sl-color-white: #4c4f69; + --sl-color-gray-1: #5c5f77; + --sl-color-gray-2: #6c6f85; + --sl-color-gray-3: #7c7f93; + --sl-color-gray-4: #9ca0b0; + --sl-color-gray-5: #bcc0cc; + --sl-color-gray-6: #ccd0da; + --sl-color-black: #eff1f5; +} -- 2.52.0 From 936f13f712749e2c749958aaaa340cccd827a5d1 Mon Sep 17 00:00:00 2001 From: rootiest Date: Sat, 25 Jul 2026 23:10:54 -0400 Subject: [PATCH 12/15] ci(docs): build and deploy the Starlight site to Cloudflare Pages Adds Node setup, an Astro site build, and a wrangler Pages deploy step to the existing docs workflow, gated on docs/site/** via the paths trigger. Also fixes astro.config.mjs's site: URL to match the fish-config-docs Cloudflare Pages project name (it previously pointed at fish-config.pages.dev, which is not the project being deployed). --- .gitea/workflows/build-docs.yml | 23 +++++++++++++++++++++++ docs/site/astro.config.mjs | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/.gitea/workflows/build-docs.yml b/.gitea/workflows/build-docs.yml index 177025f..d0d6490 100644 --- a/.gitea/workflows/build-docs.yml +++ b/.gitea/workflows/build-docs.yml @@ -9,6 +9,7 @@ on: - "docs/build-manual.py" - "docs/manualtools.py" - "docs/verify-manual.py" + - "docs/site/**" jobs: build-docs: @@ -46,6 +47,28 @@ jobs: docs/fish-config.md \ -o docs/fish-config.1 + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: "24" + + - name: Build documentation site + run: | + python3 docs/build-manual.py --site + cd docs/site + npm ci + npx astro build + + - name: Deploy to Cloudflare Pages + env: + CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }} + CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }} + run: | + cd docs/site + npx --yes wrangler pages deploy dist/ \ + --project-name=fish-config-docs \ + --branch=main + - name: Commit generated docs run: | git config user.name "Gitea Actions" diff --git a/docs/site/astro.config.mjs b/docs/site/astro.config.mjs index 195b237..440f98d 100644 --- a/docs/site/astro.config.mjs +++ b/docs/site/astro.config.mjs @@ -3,7 +3,7 @@ import starlight from '@astrojs/starlight'; import sidebar from './src/sidebar.json' with { type: 'json' }; export default defineConfig({ - site: 'https://fish-config.pages.dev', + site: 'https://fish-config-docs.pages.dev', integrations: [ starlight({ title: 'Fish Config', -- 2.52.0 From 16e969ee15e50b9be07c26c44814c20e31634a3d Mon Sep 17 00:00:00 2001 From: rootiest Date: Sat, 25 Jul 2026 23:33:26 -0400 Subject: [PATCH 13/15] chore(docs): retire wiki, chunked HTML, and split-manual pipeline docs/manual/** plus the Astro Starlight site (https://fish-config-docs.pages.dev/) replace the Gitea wiki (docs/wiki/) and chunked offline HTML (docs/html/, docs/html-style.html) as the published documentation surface. Retires the now-unused docs/split-wiki.py and docs/split-manual.py generators alongside them. - config-help --html now opens the published site root instead of resolving a local sitemap anchor; when a keyword was given it prints a note that deep links aren't available yet and to use the site's search box. - open-url and docs/manual/05-functions/14-miscellaneous.md examples repointed from docs/html/index.html to the site URL. - docs/manual/11-viewing-this-manual.md rewritten to document the four access paths: the website, the man page, in-terminal pager, and reading docs/manual/** directly. fish-config.index updated to match the new headings. - README.md documentation section and Zoxide attribution link repointed at the site; corrected the stale "single source file" claim about fish-config.md. - Regenerated docs/fish-config.md via build-manual.py --concat. --- README.md | 20 +- docs/fish-config.index | 10 +- docs/fish-config.md | 90 +- docs/html-style.html | 301 ---- docs/html/1-name.html | 495 ------- docs/html/10-6-dependency-catalog.html | 547 ------- docs/html/11-7-customization.html | 888 ------------ docs/html/12-8-fisher-plugins.html | 573 -------- docs/html/13-9-installation.html | 521 ------- docs/html/14-10-personalization.html | 540 ------- docs/html/15-11-viewing-this-manual.html | 546 ------- docs/html/2-synopsis.html | 503 ------- docs/html/3-description.html | 562 ------- docs/html/4-table-of-contents.html | 530 ------- docs/html/5-1-configuration-variables.html | 602 -------- docs/html/6-2-path-setup.html | 506 ------- docs/html/7-3-key-bindings.html | 538 ------- docs/html/8-4-abbreviations.html | 641 -------- docs/html/9-5-functions-reference.html | 1372 ------------------ docs/html/index.html | 903 ------------ docs/html/sitemap.json | 1 - docs/manual/05-functions/14-miscellaneous.md | 15 +- docs/manual/11-viewing-this-manual.md | 75 +- docs/manualtools.py | 2 +- docs/split-manual.py | 207 --- docs/split-wiki.py | 117 -- docs/verify-manual.py | 2 +- docs/wiki/1-configuration-variables.md | 138 -- docs/wiki/10-personalization.md | 64 - docs/wiki/11-viewing-this-manual.md | 74 - docs/wiki/2-path-setup.md | 22 - docs/wiki/3-key-bindings.md | 52 - docs/wiki/4-abbreviations.md | 188 --- docs/wiki/5-functions-reference.md | 1086 -------------- docs/wiki/6-dependency-catalog.md | 69 - docs/wiki/7-customization.md | 434 ------ docs/wiki/8-fisher-plugins.md | 103 -- docs/wiki/9-installation.md | 39 - docs/wiki/index.md | 79 - functions/config-help.fish | 75 +- functions/open-url.fish | 2 +- 41 files changed, 140 insertions(+), 13392 deletions(-) delete mode 100644 docs/html-style.html delete mode 100644 docs/html/1-name.html delete mode 100644 docs/html/10-6-dependency-catalog.html delete mode 100644 docs/html/11-7-customization.html delete mode 100644 docs/html/12-8-fisher-plugins.html delete mode 100644 docs/html/13-9-installation.html delete mode 100644 docs/html/14-10-personalization.html delete mode 100644 docs/html/15-11-viewing-this-manual.html delete mode 100644 docs/html/2-synopsis.html delete mode 100644 docs/html/3-description.html delete mode 100644 docs/html/4-table-of-contents.html delete mode 100644 docs/html/5-1-configuration-variables.html delete mode 100644 docs/html/6-2-path-setup.html delete mode 100644 docs/html/7-3-key-bindings.html delete mode 100644 docs/html/8-4-abbreviations.html delete mode 100644 docs/html/9-5-functions-reference.html delete mode 100644 docs/html/index.html delete mode 100644 docs/html/sitemap.json delete mode 100644 docs/split-manual.py delete mode 100644 docs/split-wiki.py delete mode 100644 docs/wiki/1-configuration-variables.md delete mode 100644 docs/wiki/10-personalization.md delete mode 100644 docs/wiki/11-viewing-this-manual.md delete mode 100644 docs/wiki/2-path-setup.md delete mode 100644 docs/wiki/3-key-bindings.md delete mode 100644 docs/wiki/4-abbreviations.md delete mode 100644 docs/wiki/5-functions-reference.md delete mode 100644 docs/wiki/6-dependency-catalog.md delete mode 100644 docs/wiki/7-customization.md delete mode 100644 docs/wiki/8-fisher-plugins.md delete mode 100644 docs/wiki/9-installation.md delete mode 100644 docs/wiki/index.md diff --git a/README.md b/README.md index 879b8cc..53738ef 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ built around a Catppuccin Mocha aesthetic with a curated set of modern CLI tool integrations, smart shell functions, and a heavily customized abbreviation system for keyboard-driven workflows. +📖 **[Documentation site](https://fish-config-docs.pages.dev/)** + ## Table of Contents - [Overview](#overview) @@ -118,11 +120,16 @@ the watcher inert without uninstalling it. ## Documentation -### [📖 Full Documentation Wiki](docs/wiki/index.md) +### [📖 Documentation Site](https://fish-config-docs.pages.dev/) -A multi-page Markdown wiki auto-generated from the single source file `docs/fish-config.md` -on every push to `main`. It covers configuration variables, key bindings, abbreviations, -all functions, the dependency catalog, customization, and more. +A Starlight-powered site generated from `docs/manual/**` — the single source +of truth — on every push to `main`. It covers configuration variables, key +bindings, abbreviations, all functions, the dependency catalog, customization, +and more, with full-text search. + +Contributing to the docs? Edit files under `docs/manual/**`, never the +generated `docs/fish-config.md` — it's rebuilt from the manual tree and any +hand-edits are discarded. To browse the docs from the terminal: @@ -130,8 +137,7 @@ To browse the docs from the terminal: |---|---| | `help config` | Open the terminal manual in the best available pager | | `help config ` | Jump directly to a section matching the keyword | -| `help config --html` | Open the pre-built HTML docs in the default browser | -| `help config --html` | Open HTML docs at the matching section anchor | +| `help config --html` | Open the documentation site in the default browser | | `help config --man` | Open the compiled man page via `man -l` | | `help config --man` | Open the man page jumping to the nearest match | | `repo-open` | Open this repo's web page in the browser (deep-links to the current branch and sub-directory) | @@ -298,7 +304,7 @@ Command shadows react immediately; bindings, prompt, and abbreviations take effe ## Attribution -The core of the [Zoxide integration](docs/wiki/2-path-setup.md) in this repository was originally adapted from the [icezyclon/zoxide.fish](https://github.com/icezyclon/zoxide.fish) plugin (MIT Licensed) and has since been heavily customized for performance and Fish 4.x compatibility. +The core of the [Zoxide integration](https://fish-config-docs.pages.dev/02-path-setup/) in this repository was originally adapted from the [icezyclon/zoxide.fish](https://github.com/icezyclon/zoxide.fish) plugin (MIT Licensed) and has since been heavily customized for performance and Fish 4.x compatibility. --- diff --git a/docs/fish-config.index b/docs/fish-config.index index 446c2c3..5528880 100644 --- a/docs/fish-config.index +++ b/docs/fish-config.index @@ -291,10 +291,10 @@ local-config=## local.fish # ── Section 11: Viewing This Manual ────────────────────────── viewing=# 11. VIEWING THIS MANUAL manual=# 11. VIEWING THIS MANUAL -ov=## With ov (recommended) +ov=## In the terminal man-page=## As a man page manpage=## As a man page -jump=## Jumping to a section -html=## In the browser (HTML) -browser=## In the browser (HTML) -wiki=## As a wiki +jump=## In the terminal +html=## The documentation website +browser=## The documentation website +site=## The documentation website diff --git a/docs/fish-config.md b/docs/fish-config.md index de72267..abf355c 100644 --- a/docs/fish-config.md +++ b/docs/fish-config.md @@ -1328,7 +1328,7 @@ Add -i (interactive confirmation) to destructive commands: ### config-help Synopsis: config-help [SECTION] - config-help [SECTION] --html + config-help --html config-help [SECTION] --man config-help -h | --help @@ -1338,11 +1338,11 @@ Add -i (interactive confirmation) to destructive commands: keyword (case-insensitive; checks fish-config.index aliases first). Flags: - --html / -w Open docs/html/index.html in the default browser. - If SECTION is given, opens at the matching anchor. - Detects the browser via xdg-mime x-scheme-handler/https, - then known binaries, then xdg-open as last resort. - Respects $fish_help_browser and $BROWSER. + --html / -w Open the published documentation website + (https://fish-config-docs.pages.dev/) in the default + browser via xdg-open. Deep links to a section aren't + supported; if SECTION is given, a note points you to the + site's search box instead. --man / -m Open docs/fish-config.1 via man -l directly. If SECTION is given, jumps to the nearest match. --help / -h Print usage and navigation key reference. @@ -1350,7 +1350,6 @@ Add -i (interactive confirmation) to destructive commands: config-help keybindings config-help pkg config-help --html - config-help pkg --html config-help --man config-help pkg --man @@ -1378,7 +1377,7 @@ Add -i (interactive confirmation) to destructive commands: 5. xdg-open (last resort) open-url https://git.rootiest.dev/rootiest/fish-config - open-url "file://$HOME/.config/fish/docs/html/index.html" + open-url -v https://fish-config-docs.pages.dev/ Used internally by config-help --html. @@ -2299,25 +2298,17 @@ local.fish in turn sources secrets.fish when it exists. # 11. VIEWING THIS MANUAL -## With ov (recommended) +There are four ways to read this manual. - help config +## The documentation website -ov renders the Markdown with syntax highlighting and section-based -navigation. + help config --html - Space next section - ^ previous section - Alt+u toggle section list sidebar - / search forward - n / N next / previous search match - g go to line number - j interactive jump target (line, %, or 'section') - q quit - -## With bat - - bat --language=markdown --paging=always ~/.config/fish/docs/fish-config.md +Opens https://fish-config-docs.pages.dev/ in the default browser — the +Starlight-powered site built from `docs/manual/**` on every push to `main`. +It has a section sidebar and full-text search. Deep links to a specific +section aren't supported from the command line; once the site opens, use +its search box to jump straight to what you need. ## As a man page @@ -2336,29 +2327,36 @@ NOTE: fish-config (hyphen) is this config's man page. fish_config (underscore) is fish's built-in browser-based configuration tool — a completely separate command. Do not mix them up. -## In the browser (HTML) +## In the terminal - help config --html - help config pkg --html + help config + help config keybindings -Opens docs/html/index.html in the default web browser. If a section -keyword is given, the browser opens directly at the matching anchor -(resolved via docs/html/sitemap.json). Browser detection queries the -system's x-scheme-handler/https MIME entry (via xdg-mime) to find the -real browser binary, then falls back through known browser binaries -(firefox, chromium, vivaldi, etc.), and finally xdg-open as a last -resort. Set $fish_help_browser or $BROWSER to override. +Without a pager available beyond the basics, `help config [SECTION]` opens +the Markdown manual in the best available viewer, falling back through: -## As a wiki + 1. ov + bat section navigation + syntax highlighting (best) + 2. ov alone section navigation, raw Markdown + 3. bat alone syntax highlighting, use / to search + 4. man -l pre-compiled man page (if available) + 5. less plain text with line-jump + 6. cat plain output -The generated Markdown wiki lives in docs/wiki/. index.md provides the -project overview and a full table of contents. Each section page has a -navigation bar at the top linking to every other section. +With ov, the Markdown renders with syntax highlighting and section-based +navigation: -The wiki is auto-generated from this file by the CI pipeline on every -push to main that changes docs/fish-config.md. + Space next section + ^ previous section + Alt+u toggle section list sidebar + / search forward + n / N next / previous search match + g go to line number + j interactive jump target (line, %, or 'section') + q quit -## Jumping to a section +If SECTION is given, the pager opens at the first heading that matches the +keyword (case-insensitive; checks `docs/fish-config.index` aliases first, +then falls back to a normalized heading scan): help config keybindings help config abbreviations @@ -2366,4 +2364,12 @@ push to main that changes docs/fish-config.md. help config logs help config fish-deps -The keyword is matched case-insensitively against section headings. +## Reading the source directly + +`docs/manual/**` is the single source of truth this manual, the man page, +and the website are all generated from. Numbered files and directories +correspond to the numbered sections in this manual — browse them in any +editor, or from a shell: + + cd ~/.config/fish/docs/manual + grep -rn "keybindings" . diff --git a/docs/html-style.html b/docs/html-style.html deleted file mode 100644 index 2cecdbc..0000000 --- a/docs/html-style.html +++ /dev/null @@ -1,301 +0,0 @@ - - diff --git a/docs/html/1-name.html b/docs/html/1-name.html deleted file mode 100644 index dbaa08f..0000000 --- a/docs/html/1-name.html +++ /dev/null @@ -1,495 +0,0 @@ - - - - - - - - NAME - - - - - -

-

NAME

-

fish-config - personal fish shell configuration for Fish 4.x with -modern CLI tool integration

- - diff --git a/docs/html/10-6-dependency-catalog.html b/docs/html/10-6-dependency-catalog.html deleted file mode 100644 index 927b32f..0000000 --- a/docs/html/10-6-dependency-catalog.html +++ /dev/null @@ -1,547 +0,0 @@ - - - - - - - - 6. DEPENDENCY CATALOG - - - - - - -

6. DEPENDENCY -CATALOG

-

fish-deps manages these tools. Run fish-deps to check -status, or fish-deps install to install missing ones.

-

Required

-
fish      Fish shell >= 4.0
-fzf       Fuzzy finder
-zoxide    Smart cd with frecency
-

Integrations

-
wakatime   Developer time tracking
-tailscale  Mesh VPN client
- -
cargo       Rust toolchain (via rustup); used by fish-deps to install
-            Rust-based tools and to build fish from source. All paths
-            are gated on type -q cargo and degrade gracefully.
-starship    Cross-shell prompt; loaded via type -q starship guard.
-            Without it the Catppuccin nim-style fallback prompt activates.
-uv          Python package and project manager (Astral); used by the
-            fish-from-source build path in fish-deps. All consumers
-            degrade gracefully without it.
-direnv      Per-directory environment loading; integration is fully
-            guarded with type -q direnv. Without it the direnv hook
-            is simply not loaded and auto-venv activates normally.
-paru        AUR helper (Arch only; preferred); guarded throughout —
-            non-Arch systems silently skip AUR-specific paths.
-yay         AUR helper (Arch only; fallback to paru); same guards apply.
-eza         Modern ls replacement
-lsd         ls replacement (fallback to eza)
-bat         Syntax-highlighted cat
-btop        Modern resource monitor
-dust        Disk usage tree (Rust)
-duf         Disk usage/free overview
-prettyping  Colorized ping wrapper
-ov          Modern pager (replaces less)
-ripgrep     Fast line search
-lazygit     Terminal git UI
-lazydocker  Terminal docker UI
-trash       Safe delete (trash-cli)
-kitty       GPU-accelerated terminal (primary)
-wezterm     GPU-accelerated terminal (alternative)
-python3     Standalone interpreter — used by the paru/yay log cleaner.
-            Note: uv does not provide python3 on PATH, and Arch's base
-            does not include it, so it is listed separately. All
-            consumers degrade gracefully without it.
-yt-dlp      Video/media downloader; backs the yt-dlp wrapper function.
-            Optional — the wrapper falls back to the system yt-dlp and
-            the rest of the config works without it.
-

Install Methods

-

The install priority for each tool:

-
cargo     Rust tools (eza, lsd, bat, dust, ov, ripgrep, trashy, zoxide,
-          starship) — always gets the latest crate version
-system PM paru / apt / brew / dnf / etc. — for tools without a crate
-git clone fzf — installed from GitHub to ~/.fzf/
-curl      starship installer, fisher bootstrap, uv installer
-
- - diff --git a/docs/html/11-7-customization.html b/docs/html/11-7-customization.html deleted file mode 100644 index 785b9a4..0000000 --- a/docs/html/11-7-customization.html +++ /dev/null @@ -1,888 +0,0 @@ - - - - - - - - 7. CUSTOMIZATION - - - - - - -

7. CUSTOMIZATION

-

Machine-local -Configuration

-

Place machine-specific settings that should not be committed to git -in:

-
$__fish_user_dots_path/local.fish
-

__fish_user_dots_path defaults to -~/.config/.user-dots/fish. Set a custom location with:

-
set -U __fish_user_dots_path /path/to/your/dots/fish
-

Typical uses: additional PATH entries, local aliases, -hostname-specific env vars, work-specific tool configs.

-

For convenience, a git-ignored user-dots symlink in the -fish config directory tracks $__fish_user_dots_path so the -overlay can be browsed from ~/.config/fish/. It is created -if missing and repointed if the path changes. Opt out by setting -__fish_user_dots_symlink to a falsy value, or toggling -"Dots link" off on the config-settings Paths page — this stops -generation and removes any existing link. It only ever manages a symlink -and never clobbers a real file or directory at that path.

-

Secrets and API -Keys

-
$__fish_user_dots_path/secrets.fish
-

Store API tokens, GPG keys, private credentials here. This file is -never committed. It is sourced by local.fish directly, not by -config.fish.

-

local.fish is sourced at the end of config.fish on every -interactive session, so it and its companion secrets.fish can override -anything set earlier.

-

Overriding Configuration -Variables

-

Any variable set in local.fish after the main config loads takes -effect. Example: to increase the scrollback history limit:

-
# in local.fish
-set -gx SCROLLBACK_HISTORY_MAX_FILES 200
-

Fish Universal -Variables

-

Some settings (fzf colors, theme) are stored in fish_variables via -set -U. These are machine-local and git-ignored. Do not -commit fish_variables.

-

Opinionated Components (Minimal -Mode)

-

Every opinionated piece of this config is active by default but can -be switched off through six category opt-out variables, each evaluated -via __fish_variable_check. Set a variable to any falsy value (0, false, -no, off, n) to disable its category; erase it or set a truthy value (1, -true, yes, on, y) to re-enable. Unset means enabled.

-

An explicit per-category truthy value takes precedence over the -master switch: setting __fish_config_opinionated=0 disables all unset -categories, but a category with an explicit truthy value remains enabled -regardless.

-
Variable                        Disables
-------------------------------  ------------------------------------
-__fish_config_op_aliases        Command shadows and flag injection:
-                                ls->eza, cat->bat, cd->zoxide,
-                                rm->trash, less->ov, top->btop,
-                                ping->prettyping, ssh->kitten,
-                                du->duf/dust, mkdir/bash wrappers,
-                                history timestamps, grep/cp/mv/wget
-                                flag injection, help intercept, claude
-                                AGENTS.md auto-link
-__fish_config_op_autoexec       Startup side-effects: Fisher
-                                bootstrap, theme apply, paru/yay
-                                wrapper generation, auto venv
-                                activation, WakaTime hook
-__fish_config_op_overrides      Key and env overrides: Vi mode,
-                                exit->smart_exit, PAGER/MANPAGER,
-                                CDPATH, bang-bang system, autopair,
-                                puffer, starship prompt, theme
-                                colors, FZF_DEFAULT_OPTS, right
-                                prompt
-__fish_config_op_integrations   Terminal/tool coupling: Kitty/
-                                WezTerm window abbreviations, done
-                                notifications, spwin/tab/split,
-                                hist, logs, upgrade, WakaTime
-__fish_config_op_logging        Logging & capture: scrollback
-                                capture on exit, paru/yay AUR log
-                                wrappers, Kitty watcher capture;
-                                sentinel file coordinates
-                                cross-process state
-__fish_config_op_greeting       Greeting & first-run UI: per-session
-                                fish_greeting override (defines empty
-                                function late in config.fish to
-                                suppress distro greetings such as
-                                CachyOS fastfetch); first-run welcome
-                                banner in conf.d/first_run.fish
-

Examples:

-
# Disable command shadows only (rm becomes plain rm again):
-set -U __fish_config_op_aliases off
-
-# Full minimal mode — disable all six categories at once:
-set -U __fish_config_opinionated 0
-
-# Re-enable everything:
-set -Ue __fish_config_opinionated
-
-# Minimal mode but keep the greeting:
-set -U __fish_config_opinionated 0
-set -U __fish_config_op_greeting 1
-# (erase both to go back to full-flavor defaults)
-

For an interactive alternative to setting these variables by hand, -run config-settings — a full-screen TUI that flips any category -(including C5 logging) on or off, per session or universally. See its -entry in Section 5.

-

Notes:

-
    -
  • Command shadows (rm, cat, ls, ...) react immediately; conf.d-level -components (bindings, prompt, abbreviations, hooks) take effect in new -shells.
  • -
  • With aliases disabled, rm falls back to bare command rm -— files are deleted permanently, not trashed.
  • -
  • Disabled integration commands (spwin, tab, split, hist, logs, -upgrade) print an error naming the variable that disabled them.
  • -
  • On CachyOS, the distro fish config's own aliases, history override, -and bang-bang bindings are stripped per category as well.
  • -
-

Component -Reference

-

The following tables detail every component in each category. Use -this reference to understand exactly which behaviors change when you -toggle a category variable.

-

C1 — Command -Shadows

-

Disabling __fish_config_op_aliases restores standard system behavior -for all of these commands.

-
Command / Alias    Active behavior                       Disabled fallback
-───────────────────────────────────────────────────────────────────────────
-ls                 eza -l -a --icons --hyperlink          system ls
-cat                bat syntax-highlighted; dirs → ls      /usr/bin/cat
-cd                 zoxide frecency-based navigation        fish builtin cd
-rm                 moves files to trash (recoverable)     command rm (permanent)
-less               $PAGER → ov → less → more → cat       system less
-du                 duf (disk overview) or dust (dir tree) system du
-top                btop resource monitor                  system top
-ping               prettyping --nolegend animation        system ping
-ssh                kitten ssh in Kitty terminal           system ssh
-rg                 rg --hyperlink-format=kitty            system rg
-mkdir              verbose path-tree display on creation  mkdir -p silently
-bash               XDG bashrc + $SHELL reset on exit      system bash
-history            timestamps prepended to every entry    fish builtin history
-cp / mv            forced -i confirmation prompt          cp / mv unmodified
-wget               forced --continue (resume downloads)   system wget
-grep/fgrep/egrep   forced --color=auto                    system grep variants
-dir / vdir         forced --color=auto                    system dir / vdir
-help config        intercepts "help config" → config-help fish builtin help
-claude             auto-links AGENTS.md as CLAUDE.md before launch command claude
-edit               multi-editor launcher (GUI/term + fallbacks)  $EDITOR/nvim/nano/vi
-

When C1 is disabled, rm uses bare -command rm with no wrapper — files are permanently deleted, -not trashed. There is no intermediate safety net.

-

C2 — Startup -Side-Effects

-

These run automatically without any user action. Disabling -__fish_config_op_autoexec prevents all of them.

-
Component                  Trigger              What it does
-───────────────────────────────────────────────────────────────────────────
-Fisher bootstrap           First shell only     Downloads and installs fisher
-Fisher update              After bootstrap      Installs all fish_plugins entries
-Catppuccin Mocha theme     First shell only     Applies theme via fish_config
-paru wrapper               Every startup        Writes ~/.local/bin/paru wrapper
-yay wrapper                Every startup        Writes ~/.local/bin/yay wrapper
-Python venv activation     On every cd          Sources .venv/bin/activate.fish
-WakaTime command hook      On every command     Reports to WakaTime API
-Auto-pull fast-forward     On entering a repo   Background ff-only git pull
-user-dots symlink          Every startup        Links $__fish_config_dir/user-dots
-                                                to $__fish_user_dots_path
-

When C2 is disabled: no Fisher install, no theme application, no -paru/yay wrapper generation, no automatic venv activation, no WakaTime -reporting, no auto-pull (the PWD handler is never registered), and the -user-dots convenience symlink is not created. The symlink is git-ignored -and only ever managed as a symlink — a real file or directory at that -path is left untouched. The symlink has its own opt-out independent of -C2: set __fish_user_dots_symlink to a falsy value (or toggle "Dots link" -off on the config-settings Paths page) to stop generating it and remove -any existing link — honoured even when C2 is enabled. Managed by the -__fish_user_dots_link helper. The first-run completion marker -(__fish_config_first_run_complete) is still set so the init does not -re-run on subsequent shells.

-

Python venv activation fires on every directory change. If a -directory uses direnv (.envrc present), direnv takes priority and -auto-venv is skipped for that directory.

-

Auto-pull fast-forwards opted-in repositories in the background when -you cd into them. The fish-config repo is always covered; other repos -are added with the auto-pull command (see its entry in the -functions reference). It only ever fast-forwards a clean repo whose -branch has an upstream — never rebases, merges, or overwrites work — so -it is a no-op on dirty trees, divergent branches, or repos without a -remote. The handler fires once per repo entry (not on every -sub-directory cd). The registry is machine-local at -$__fish_user_dots_path/auto-pull.list (defaults to -~/.config/.user-dots/fish/auto-pull.list) and is never -committed.

-

C3 — -Key and Environment Overrides

-

These change fundamental shell behavior: how keys work, which pager -opens, and what the prompt looks like. Disabling -__fish_config_op_overrides removes all of them.

-
Override                  What it replaces or sets
-───────────────────────────────────────────────────────────────────────────
-Vi mode                   fish_vi_key_bindings replaces default Emacs mode
-exit → smart_exit         exit wrapper that captures scrollback before closing
-PAGER=ov                  ov used by git, man, and all $PAGER-aware tools
-MANPAGER=bat pipeline     man pages rendered with syntax highlighting
-CDPATH=. ~/projects ~     bare dir names resolve against ~/projects and ~
-Bang-bang system          ! and $ keys expand history; !^, !*, !-N, !?str?,
-                          ^old^new abbreviations; six expand_bang_* helpers
-Autopair                  ( [ { " ' auto-close to (), [], {}, "", ''
-Puffer key intercepts     . ! $ * keys intercepted for smart expansion
-Starship prompt           fish_prompt replaced by Starship + OSC 133 markers
-Catppuccin colors         30+ fish_color_* variables set to Mocha palette
-FZF_DEFAULT_OPTS          FZF themed to Catppuccin Mocha colors
-Right prompt              fish_right_prompt: exit code (on failure) + dim timestamp; always rendered; Docker context added when starship+C3 active
-

The bang-bang system spans key_bindings.fish, abbr.fish, puffer.fish, -and six expand_bang_*.fish functions. All are gated together — disabling -C3 removes the entire bang-expansion system at once.

-

When C3 is disabled, exit falls back to -builtin exit with no scrollback capture, no Kitty IPC, and -no file I/O on exit. The scrollback capture block is independently -controlled by C5 (see below).

-

C4 — -Terminal and Tool Integration

-

These features couple the shell to specific external tools. Disabling -__fish_config_op_integrations disables all of them.

-
Component                  Requires
-───────────────────────────────────────────────────────────────────────────
-~60 Kitty/WezTerm abbrs    Active Kitty or WezTerm session
-  (:w, :wv, :wh, :t, etc.)
-Done desktop notifications Graphical desktop with a notification daemon
-spwin                      Kitty or WezTerm
-tab                        Kitty, WezTerm, or Konsole
-split                      Kitty or WezTerm
-hist                       fzf + wl-copy (Wayland clipboard)
-logs                       fzf + ov; reads from ~/.terminal_history/
-upgrade                    paru or yay (Arch Linux only)
-WakaTime hook              wakatime CLI and a configured API key
-

Disabled integration commands (spwin, tab, split, hist, logs, -upgrade) print a colored error to stderr naming the variable that -disabled them rather than silently failing.

-

C5 — Logging and -Capture

-

Five components capture shell output to disk. Disabling -__fish_config_op_logging skips all capture and removes the logging -wrappers.

-
Component               What it captures
-───────────────────────────────────────────────────────────────────────────
-Scrollback capture      Terminal session output saved to:
-                        ~/.terminal_history/scrollback_YYYY-MM-DD_HH-MM-SS.log
-tmux pane capture       Continuous pane stream via pipe-pane, saved to:
-                        ~/.terminal_history/tmux_<session>-w<win>-p<pane>_YYYY-MM-DD_HH-MM-SS.log
-zellij pane capture     Pane scrollback snapshot on shell exit, saved to:
-                        ~/.terminal_history/zellij_<session>-p<pane>_YYYY-MM-DD_HH-MM-SS.log
-paru wrapper            All paru/AUR output captured to:
-                        ~/.terminal_history/paru_YYYY-MM-DD_HH-MM-SS.log
-yay wrapper             All yay/AUR output captured to:
-                        ~/.terminal_history/yay_YYYY-MM-DD_HH-MM-SS.log
-Kitty watcher           watcher.py captures scrollback when Kitty closes
-

The tmux capture starts automatically when fish launches inside any -tmux pane ($TMUX is set). It uses tmux's native pipe-pane to stream all -pane output directly to disk without an intermediate process. Each fish -shell session gets its own log file; a new log is created on each shell -start (including exec fish and new splits). Before each new log, the -oldest tmux_*.log files are pruned (by modification time) to keep the -total within SCROLLBACK_HISTORY_MAX_FILES, matching the paru/yay wrapper -behaviour.

-

The zellij capture works differently: Zellij has no live -output-streaming facility like pipe-pane, so the log is taken as a -one-shot snapshot when the shell exits, via -zellij action dump-screen --full --ansi (the --ansi flag -preserves color). The dump is captured on the fish process's stdout and -written to the log file by fish itself (not via --path, -which would make the zellij server write the file). A fish_exit handler -(registered whenever $ZELLIJ is set) writes the pane's full scrollback -and then prunes old zellij_*.log files the same way. Because the capture -happens at exit, toggling __fish_config_op_logging takes effect on the -next exit with no restart or sentinel coordination needed — the C5 guard -is re-checked when the handler fires.

-

LIMITATION — zellij capture only fires on a clean shell exit (typing -exit, Ctrl-D, or a logout), because that is when the -fish_exit handler runs. It does NOT capture when you close a pane or -quit zellij through zellij itself:

-
    -
  • Closing a pane signals the shell and tears the pane down -concurrently, so even if the handler runs, dump-screen may -find the pane buffer already gone.
  • -
  • Quitting zellij kills the zellij server, and -dump-screen needs a live server to read from — there is -nothing left to snapshot.
  • -
-

This is a structural difference from tmux, NOT a bug. tmux streams -pane output to disk continuously via pipe-pane, so whatever was printed -is already saved no matter how the pane dies. Zellij can only snapshot, -and the only reliable snapshot point from the shell is a clean exit. To -guarantee a zellij pane is logged, end the session with -exit or Ctrl-D rather than zellij's close-pane or quit -actions.

-

The Kitty watcher is managed by the kitty-logging command: it -symlinks the watcher (fish-config-watcher.py) into the Kitty config -directory and wires it into kitty.conf via a managed block. Inside -Kitty, a non-blocking per-session reminder points first-time users at -kitty-logging install until they install or run -kitty-logging dismiss. Install affects new Kitty windows -only; runtime disable is still handled by the .logging_disabled -sentinel.

-

Logging coordination via sentinel file

-

C5 uses a sentinel file to synchronize state between the shell and -out-of-process components (the Kitty watcher and all running -shells):

-
~/.config/fish/.logging_disabled
-

Disabling __fish_config_op_logging:

-
    -
  1. Creates the sentinel immediately in every open shell.
  2. -
  3. Removes ~/.local/bin/paru and ~/.local/bin/yay logging wrappers; -bare /usr/bin/paru and /usr/bin/yay are used instead.
  4. -
  5. Kitty's watcher.py reads the sentinel on each save attempt and skips -capture — no Kitty restart required.
  6. -
  7. smart_exit stops saving scrollback logs.
  8. -
  9. Stops tmux pipe-pane capture in every open fish shell inside -tmux.
  10. -
-

Re-enabling __fish_config_op_logging:

-
    -
  1. Removes the sentinel in every open shell.
  2. -
  3. Regenerates paru/yay logging wrappers in ~/.local/bin/.
  4. -
  5. Kitty watcher resumes capture on the next session exit.
  6. -
  7. Restarts tmux pipe-pane capture in every open fish shell inside -tmux.
  8. -
-

Changes propagate to all running shells through an event handler that -fires whenever __fish_config_op_logging changes — no shell restart -needed.

-

Note: C3 and C5 compose independently. C3 controls whether the -smart_exit wrapper is active at all; C5 controls only the -scrollback-capture block inside it. With C3 disabled, exit is plain -builtin exit regardless of C5.

-

C6 — -Greeting and First-Run UI

-
Component                  What it shows
-───────────────────────────────────────────────────────────────────────────
-First-run welcome banner   One-time message on first interactive session
-fish_greeting override     Empty function defined late in config.fish to
-                           suppress distro greetings (e.g. CachyOS sets
-                           fish_greeting to fastfetch by default)
-

When C6 is disabled, no greeting is printed by this config. Any -greeting set by the distro or other configs runs normally — this config -simply does not override it.

-

Prompt and Theme

-

Starship

-

The primary prompt is Starship, initialized by conf.d/starship.fish. -Configure it via ~/.config/starship.toml.

-

conf.d/starship.fish defines a fish_prompt wrapper that only -activates when starship is in PATH. It emits OSC 133;A (prompt start) -immediately before Starship renders and OSC 133;B (input start) -immediately after, placing both markers on the prompt line itself. This -allows ov to use them as sticky section headers when browsing scrollback -logs. Without Starship, fish's built-in prompt handles these markers -automatically.

-

Catppuccin -Fallback Prompt

-

When Starship is absent or C3 overrides are disabled, a built-in -nim-style two-line prompt activates from functions/fish_prompt.fish. No -external dependencies — fish builtins only.

-

Layout:

-
┬─[user@host:~/path] (main)
-╰─>$
-

Elements:

-
user        Yellow (Catppuccin Yellow); red if root
-@host       Blue (local) or Teal (SSH)
-~/path      prompt_pwd abbreviation (Catppuccin Text)
-(main)      Current git branch in Catppuccin Pink; omitted outside repos
-─[V:name]   Active Python venv basename; omitted when none
-─[N/I/R/V]  Vi-mode indicator when vi bindings are active
-┬─ / ╰─>    Connector lines: Catppuccin Green on success, Red on failure
-

The right prompt (fish_right_prompt.fish) always renders, regardless -of C3 state. On failure it shows a red ✘ and the exit code; on success -it shows only the dim timestamp. When starship is installed and C3 is -enabled, the active Docker context is also shown (if non-default):

-
✘ 1   󰡨 myctx   Fri Jun 12 00:51:21 2026     ← failed, starship+C3 active
-✘ 1   Fri Jun 12 00:51:21 2026               ← failed, fallback prompt
-Fri Jun 12 00:51:21 2026                     ← success (no ✘)
-

FZF

-

FZF is themed to Catppuccin Mocha via FZF_DEFAULT_OPTS set in -integrations/fzf.fish. The colors applied:

-
Background:   #1E1E2E (base)    #313244 (surface0)
-Foreground:   #CDD6F4 (text)
-Highlights:   #F38BA8 (red)     #CBA6F7 (mauve)    #B4BEFE (lavender)
-

To customize, override FZF_DEFAULT_OPTS in local.fish.

-

Catppuccin Mocha Syntax -Highlighting

-

The Catppuccin Mocha theme ships with this config in themes/ and is -applied on first run via conf.d/first_run.fish. Colors are -stored in fish_variables (universal). To switch variants, install a -different theme from themes/:

-
fish_config theme save "Catppuccin Latte"
-
- - diff --git a/docs/html/12-8-fisher-plugins.html b/docs/html/12-8-fisher-plugins.html deleted file mode 100644 index 3c782ed..0000000 --- a/docs/html/12-8-fisher-plugins.html +++ /dev/null @@ -1,573 +0,0 @@ - - - - - - - - 8. FISHER PLUGINS - - - - - - -

8. FISHER PLUGINS

-

Fisher is bootstrapped automatically on the first interactive -session via conf.d/first_run.fish. This also -applies the Catppuccin Mocha theme and prints a one-time welcome message -(gated by __fish_config_op_greeting; set it to 0 to suppress). -Subsequent sessions skip all first-run logic with zero overhead.

-

To re-trigger first-run initialization (e.g., after a fresh install -or for testing), run:

-
set -Ue __fish_config_first_run_complete
-

Then open a new shell.

-

Fisher-Managed -Plugins

-

The following plugins are fully managed by Fisher. Their files are -installed into the repo directory by Fisher and are listed in -.gitignore — do not commit them. Fisher installs and -updates them automatically.

-
jorgebucaran/fisher           Plugin manager itself
-meaningful-ooo/sponge         Remove failed commands from history
-

Sponge History -Filtering

-

Sponge removes failed commands from history and, via -conf.d/sponge_privacy.fish, also filters privacy-sensitive commands -through three layers:

-

Layer 1 — Static patterns (universal, persistent across sessions): -Commands matching any of these structural signatures are never -recorded:

-
--password / --token / --passphrase / --api-key flags with values
-Inline env assignments: GITHUB_TOKEN=xxx, MY_API_KEY=abc
-Fish set with sensitive names: set -gx GITHUB_TOKEN xxx
-URLs with embedded credentials: https://user:pass@host
-HTTP Authorization headers: curl -H "Authorization: ..."
-Basic auth flags: curl -u user:pass
-sshpass, docker login -p, openssl -passin/-passout
-

Layer 2 — Dynamic secret values (session globals, refreshed each -login): On the first prompt, after secrets.fish has loaded, the literal -values of all exported variables whose names suggest credentials (TOKEN, -PASSWORD, SECRET, API_KEY, etc.) are collected, regex-escaped, and added -as a session-scoped overlay. Because globals shadow universals in Fish, -the combined list is what sponge sees. Rotating a token takes effect on -the next login automatically.

-

Layer 3 — Per-command filter (sponge_filter_secrets): Catches -credentials in variables exported after login, such as tokens sourced -from a project .env file mid-session.

-

To add your own persistent patterns:

-
set -U -a sponge_regex_patterns 'your-regex-here'
-

To mark additional variable NAMES as credential-bearing (so Layer 2 -scrubs their values), add name tokens — via config-settings -→ Sponge, or directly:

-
set -U -a __fish_sponge_extra_sensitive ACME_API VAULT_PW
-

Tokens are folded into the Layer 2 name match case-insensitively as -substrings, so ACME_API also covers ACME_API_KEY. (The match uses ---entire to return the full variable name, so partial-name -tokens dereference the right value.)

-

The config-settings Sponge page also surfaces sponge's -own tuning variables — sponge_delay, sponge_successful_exit_codes, -sponge_purge_only_on_exit, and sponge_allow_previously_successful — so -they can be changed without typing variable names.

-

Bundled Plugin -Functionality

-

The remaining plugin functionality is bundled directly with this -config rather than managed through Fisher. The bundled versions include -customizations for Fish 4.x compatibility and improved behavior that -differ from their upstream releases. Installing them through Fisher -would overwrite these customizations.

-

Bundled components and their upstream origins:

-
catppuccin/fish               → themes/ + conf.d/theme.fish
-PatrickF1/fzf.fish            → functions/_fzf_*.fish + conf.d/fzf.fish
-franciscolourenco/done        → conf.d/done.fish
-jorgebucaran/autopair.fish    → functions/_autopair_*.fish + conf.d/autopair.fish
-nickeb96/puffer-fish          → functions/_puffer_fish_*.fish + conf.d/puffer.fish
-

Do not run fisher install for these — it will overwrite -the customized versions. To update their behavior, edit the relevant -bundled files directly.

-

fish_plugins -Manifest

-

The fish_plugins file at the config root:

-
jorgebucaran/fisher           Plugin manager itself
-meaningful-ooo/sponge         Remove failed commands from history
-

To update all Fisher-managed plugins, run fisher update -or fish-deps update which calls it as its first step.

-
- - diff --git a/docs/html/13-9-installation.html b/docs/html/13-9-installation.html deleted file mode 100644 index 0cd51d6..0000000 --- a/docs/html/13-9-installation.html +++ /dev/null @@ -1,521 +0,0 @@ - - - - - - - - 9. INSTALLATION - - - - - - -

9. INSTALLATION

-

This configuration is managed as a git repository. To deploy on a new -machine:

-
mv ~/.config/fish ~/.config/fish.bak   # back up any existing config
-git clone https://git.rootiest.dev/rootiest/fish-config.git ~/.config/fish
-

Then open a new Fish shell. Fisher installs automatically on first -launch and the Catppuccin Mocha theme is applied. All other plugin -functionality is bundled directly with this config and requires no -additional installation.

-

Return Sentinel

-

config.fish ends with a return sentinel guard. Any lines appended -after it by a tool's setup command (starship init fish | source, zoxide -init fish | source, etc.) will have no effect. All integrations are -managed via conf.d/ files.

-

If a new tool's shell integration appears to do nothing, check -whether its setup command appended an init line below the sentinel and -create a dedicated conf.d/.fish instead.

-

Updating

-

Pull the latest changes from the upstream repository without needing -a configured git remote:

-
config-update              Fetch and apply the latest commits from upstream
-config-update --dry-run    Preview available changes without applying them
-config-update --force      Stash local changes, pull, then restore the stash
-

The remote URL (https://git.rootiest.dev/rootiest/fish-config.git) -is hard-coded, so this works on a fresh clone with no origin configured. -All git output is suppressed. Run exec fish after a successful update to -reload.

-
- - diff --git a/docs/html/14-10-personalization.html b/docs/html/14-10-personalization.html deleted file mode 100644 index e7f6a92..0000000 --- a/docs/html/14-10-personalization.html +++ /dev/null @@ -1,540 +0,0 @@ - - - - - - - - 10. PERSONALIZATION - - - - - - -

10. PERSONALIZATION

-

Sensitive credentials and machine-specific settings are kept out of -version control in a private directory. The path defaults to -~/.config/.user-dots/fish/ but can be overridden:

-
set -U __fish_user_dots_path /path/to/your/dots/fish
-

Or use the interactive TUI — run config-settings and -navigate to the "Dots Path" row (last row). Press Enter to type a new -path, or ← / h to reset to the default.

-

config.fish sources local.fish from that directory on every -interactive session. local.fish is responsible for sourcing its own -secrets.fish:

-
$__fish_user_dots_path/
-├── secrets.fish   API keys, tokens, passwords, personal identifiers
-└── local.fish     Machine-specific paths, env vars, and sourcing secrets
-

fish_variables (auto-managed by fish) is excluded from this repo via -.gitignore. Do not commit it.

-

secrets.fish

-

Store anything you would not commit to a public repo: API keys, auth -tokens, passwords, and personal identifiers.

-
set -gx MY_NAME "Your Name"
-set -gx MY_EMAIL "you@example.com"
-set -gx GPG_RECIPIENT "you@example.com"
-set -gx GITHUB_TOKEN ghp_yourTokenHere
-set -gx OPENAI_API_KEY sk-proj-yourKeyHere
-set -gx GITEA_TOKEN yourGiteaTokenHere
-set -gx GITEA_CHOSEN_LOGIN your.gitea.instance
-set -gx KOPIA_PASSWORD yourKopiaPassword
-

local.fish

-

Store paths and variables specific to one machine — things that would -be wrong on any other system.

-
# CDPATH — directories searched by cd
-set -gx CDPATH . /home/youruser/projects /home/youruser
-
-# Path to your shared .gitignore boilerplate
-set -gx GITIGNORE_BOILERPLATE ~/.config/git/gitignore_boilerplate
-
-# SSH shortcuts
-abbr -a sshr 'ssh you@your-server.local'
-abbr -a sshw 'ssh you@work-server.example.com'
-
-# Docker context shortcuts
-abbr -a dcr 'docker context use my-remote-server'
-abbr -a dcw 'docker context use work-server'
-

local.fish is sourced at the end of config.fish with an existence -check so the public config works cleanly on any machine without the -private repo. local.fish in turn sources secrets.fish when it -exists.

-
- - diff --git a/docs/html/15-11-viewing-this-manual.html b/docs/html/15-11-viewing-this-manual.html deleted file mode 100644 index b3d65f7..0000000 --- a/docs/html/15-11-viewing-this-manual.html +++ /dev/null @@ -1,546 +0,0 @@ - - - - - - - - 11. VIEWING THIS MANUAL - - - - - - -

11. VIEWING THIS -MANUAL

- -
help config
-

ov renders the Markdown with syntax highlighting and section-based -navigation.

-
Space       next section
-^           previous section
-Alt+u       toggle section list sidebar
-/           search forward
-n / N       next / previous search match
-g           go to line number
-j           interactive jump target (line, %, or 'section')
-q           quit
-

With bat

-
bat --language=markdown --paging=always ~/.config/fish/docs/fish-config.md
-

As a man page

-
help config --man
-help config pkg --man
-

Opens the compiled docs/fish-config.1 directly via man -l, bypassing -the pager fallback chain. If a section keyword is given, the pager opens -at the nearest matching heading. The symlink is created once on first -run (like an install step) and MANPATH is set each session, enabling the -standard invocation:

-
man fish-config
-

NOTE: fish-config (hyphen) is this config's man page. fish_config -(underscore) is fish's built-in browser-based configuration tool — a -completely separate command. Do not mix them up.

-

In the browser -(HTML)

-
help config --html
-help config pkg --html
-

Opens docs/html/index.html in the default web browser. If a section -keyword is given, the browser opens directly at the matching anchor -(resolved via docs/html/sitemap.json). Browser detection queries the -system's x-scheme-handler/https MIME entry (via xdg-mime) to find the -real browser binary, then falls back through known browser binaries -(firefox, chromium, vivaldi, etc.), and finally xdg-open as a last -resort. Set $fish_help_browser or $BROWSER to override.

-

As a wiki

-

The generated Markdown wiki lives in docs/wiki/. index.md provides -the project overview and a full table of contents. Each section page has -a navigation bar at the top linking to every other section.

-

The wiki is auto-generated from this file by the CI pipeline on every -push to main that changes docs/fish-config.md.

-

Jumping to a -section

-
help config keybindings
-help config abbreviations
-help config pkg
-help config logs
-help config fish-deps
-

The keyword is matched case-insensitively against section -headings.

- - diff --git a/docs/html/2-synopsis.html b/docs/html/2-synopsis.html deleted file mode 100644 index 6168e18..0000000 --- a/docs/html/2-synopsis.html +++ /dev/null @@ -1,503 +0,0 @@ - - - - - - - - SYNOPSIS - - - - - - -

SYNOPSIS

-
help config [SECTION]
-

Open this manual in the best available pager. Optionally jump to a -section by keyword:

-
help config keybindings
-help config pkg
-help config abbreviations
-help config logs
-

The help config syntax integrates with fish's built-in -help command. The underlying config-help function is also -available directly.

- - diff --git a/docs/html/3-description.html b/docs/html/3-description.html deleted file mode 100644 index 645219e..0000000 --- a/docs/html/3-description.html +++ /dev/null @@ -1,562 +0,0 @@ - - - - - - - - DESCRIPTION - - - - - - -

DESCRIPTION

-

A production-grade Fish shell configuration targeting Fish 4.x. It -provides:

-
    -
  • Drop-in replacements for common Unix tools (ls, cat, rm, du, ping, -less)
  • -
  • Deep Kitty and WezTerm terminal integration: tab/window/pane -management from the command line
  • -
  • Automatic session logging: terminal scrollback, tmux/zellij panes, -and paru/yay output captured to ~/.terminal_history (on by default; see -below)
  • -
  • Automatic Python virtualenv activation on directory change
  • -
  • Cross-platform package management via pkg and fish-deps
  • -
  • AI session helpers for Claude Code and Antigravity
  • -
  • Catppuccin Mocha color theme throughout
  • -
-
-

CAUTION - SESSION LOGGING IS ON BY DEFAULT

-

This configuration silently records terminal output to -~/.terminal_history: Kitty scrollback on window close, live -tmux pane streams, zellij pane snapshots on exit, and full paru/yay -output. These logs can contain command output, file contents, and -secrets printed to the terminal. Nothing leaves your machine, but the -files persist locally.

-
    -
  • Disable all logging with: -set -U __fish_config_op_logging off
  • -
  • Prefer a menu? Run the interactive picker: -config-settings
  • -
  • See Section 7 (C5 - Logging and Capture) for the full -breakdown.
  • -
-
-

The configuration is split across:

-
config.fish               Main entry point; sets env vars and PATH
-conf.d/
-  abbr.fish               All abbreviations
-  autopair.fish           Auto-pair brackets and quotes (bundled from jorgebucaran/autopair.fish)
-  cheat.fish              cheat.sh tab completions
-  done.fish               Desktop notifications for long commands
-  first_run.fish          One-time init: Fisher bootstrap, theme, welcome
-  key_bindings.fish       Custom key bindings and Vi mode
-  logging-events.fish     C5 --on-variable event handlers; syncs logging state at startup
-  kitty-watcher-reminder.fish  C5 per-session reminder to set up the Kitty watcher
-  paru-wrapper.fish       Auto-generates ~/.local/bin/paru logging wrapper
-  puffer.fish             !! / !$ / ./ expansion (bundled from nickeb96/puffer-fish)
-  tmux-logging.fish       C5 starts tmux pipe-pane capture when fish runs inside tmux
-  zellij-logging.fish     C5 fish_exit handler dumping zellij pane scrollback on exit
-  sponge_privacy.fish     Sponge privacy patterns; filters credentials from history
-  starship.fish           fish_prompt with OSC 133 shell-integration markers
-  tailscale.fish          Tailscale CLI tab completions
-  theme.fish              Catppuccin syntax highlight colors
-  tricks.fish             PATH, bang-bang helpers, bat man pages, aliases
-  wakatime.fish           WakaTime shell hook
-  yay-wrapper.fish        Auto-generates ~/.local/bin/yay logging wrapper
-  zoxide.fish             Zoxide z/zi integration; overrides cd
-functions/                Custom functions, one per file, autoloaded
-completions/              Tab completion scripts
-integrations/
-  fzf.fish                FZF Catppuccin theme and key binding config
-scripts/
-  clean_progress_log.py   Strips paru/yay typescript animations to clean static logs
-  agents-tools/           AGENTS.md version-bump script and git hooks (wired via core.hooksPath)
-docs/                     Offline documentation and compiled man page
-  fish-config.md          Primary source manual (terminal-readable)
-  fish-config.1           Compiled man page (auto-generated by CI)
-  fish-config.index       Section index for help config navigation
-  html/                   Chunked HTML docs (auto-generated by CI)
-  wiki/                   Markdown wiki (auto-generated by CI)
-
- - diff --git a/docs/html/4-table-of-contents.html b/docs/html/4-table-of-contents.html deleted file mode 100644 index ceaee13..0000000 --- a/docs/html/4-table-of-contents.html +++ /dev/null @@ -1,530 +0,0 @@ - - - - - - - - TABLE OF CONTENTS - - - - - - -

TABLE OF CONTENTS

-
1.  Configuration Variables
-2.  PATH Setup
-3.  Key Bindings
-4.  Abbreviations
-    4.1  Editors
-    4.2  Navigation and Listing
-    4.3  Git
-    4.4  Terminal Windows, Tabs, and Panes
-    4.5  Chezmoi
-    4.6  Docker
-    4.7  Systemctl
-    4.8  AI Assistants
-    4.9  History Expansion
-    4.10 Miscellaneous
-    4.11 Shell Aliases
-5.  Functions Reference
-    5.1  File and Directory
-    5.2  Navigation
-    5.3  Editors and Viewers
-    5.4  Git and Version Control
-    5.5  Package Management
-    5.6  Dependency Management
-    5.7  System and Monitoring
-    5.8  Terminal Management
-    5.9  Clipboard
-    5.10 Network
-    5.11 Pager and Logging
-    5.12 AI and Developer Tools
-    5.13 Media and Utilities
-    5.14 Miscellaneous
-6.  Dependency Catalog
-7.  Customization
-8.  Fisher Plugins
-9.  Installation
-10. Personalization
-11. Viewing This Manual
-
- - diff --git a/docs/html/5-1-configuration-variables.html b/docs/html/5-1-configuration-variables.html deleted file mode 100644 index 1ad5bf0..0000000 --- a/docs/html/5-1-configuration-variables.html +++ /dev/null @@ -1,602 +0,0 @@ - - - - - - - - 1. CONFIGURATION VARIABLES - - - - - - -

1. CONFIGURATION -VARIABLES

-

These variables are exported from config.fish on every interactive -session. Override them in local.fish (see Section 10, -Personalization).

-

Environment -Directories (XDG)

-
XDG_CONFIG_HOME    ~/.config
-XDG_CACHE_HOME     ~/.cache
-XDG_DATA_HOME      ~/.local/share
-XDG_STATE_HOME     ~/.local/state
-

Tools that respect XDG are directed to these paths rather than -polluting $HOME.

-

Tool Homes -(XDG-compliant)

-
CARGO_HOME         $XDG_DATA_HOME/cargo
-RUSTUP_HOME        $XDG_DATA_HOME/rustup
-GOPATH             $XDG_DATA_HOME/go
-BUN_INSTALL        $XDG_DATA_HOME/bun
-NPM_CONFIG_PREFIX  $XDG_DATA_HOME/npm-global
-GNUPGHOME          $XDG_CONFIG_HOME/gnupg
-WAKATIME_HOME      $XDG_CONFIG_HOME/wakatime
-

Editor and Pager

-
EDITOR      nvim (falls back to vi if nvim is absent)
-VISUAL      unset by default; set a GUI editor via local.fish (the edit
-            function falls back to a GUI chain when VISUAL is empty)
-SUDO_EDITOR same as EDITOR
-PAGER       ov (falls back to less)
-

Scrollback History

-
__fish_scrollback_history_dir        (unset → ~/.terminal_history)
-__fish_scrollback_history_max_files  (unset → 100)
-SCROLLBACK_HISTORY_DIR        ~/.terminal_history    (exported mirror)
-SCROLLBACK_HISTORY_MAX_FILES  100                    (exported mirror)
-

The fish_scrollback_history* universal variables are the -fish-style source of truth — set them via config-settings → -Paths, or set -U directly. config.fish exports the -SCROLLBACK_HISTORY* mirrors from them, because the POSIX wrapper -scripts (paru/yay/tmux/zellij logging and _prune_terminal_logs) read the -exported names from the environment. When the _fish vars are -unset, the documented defaults are exported. config.fish deliberately -does not create a global source var, which would shadow the universal -and stop live edits from taking effect.

-

Scrollback logs accumulate in SCROLLBACK_HISTORY_DIR as timestamped -files. When the count exceeds SCROLLBACK_HISTORY_MAX_FILES the oldest -are pruned automatically on exit. Use logs to browse them -interactively.

-

Other

-
GPG_TTY              $(tty)  — ensures GPG passphrase prompts work
-CLAUDE_CODE_NO_FLICKER  1    — suppress terminal flicker in Claude Code
-CDPATH               . ~/projects ~
-

Opinionated defaults (CDPATH, PAGER/MANPAGER, Vi mode, command -shadows, terminal integrations) can be switched off per category with -universal variables — see Section 7, "Opinionated Components (Minimal -Mode)".

-

Pager Hierarchy

-

$PAGER is set to ov when available, falling back to less. The less -wrapper function extends this into a full chain so anything that calls -less directly also benefits:

-
$PAGER → ov → less → more → cat
-

When bat is installed, man pages are rendered with syntax -highlighting:

-
MANROFFOPT   -c
-MANPAGER     sh -c 'col -bx | bat -l man -p'
-

Integrations

-

Zoxide

-

cd, z, and cdi/zi are all mapped to zoxide-backed navigation. Tab -completions for cd and z blend standard directory entries (CWD and -CDPATH) with frecency results so both familiar and frequently-visited -paths appear in one list.

-

DirEnv

-

Automatically loads .envrc files on directory change. Takes priority -over the auto-venv logic — if a directory is managed by direnv, the -auto-venv activation is skipped entirely.

-

Auto Python Venv

-

When entering a directory that contains a .venv/, the virtualenv is -activated automatically and deactivated when you leave the project -tree.

-

WakaTime

-

Every shell command is reported to WakaTime for time-tracking. Set -FISH_WAKATIME_DISABLED=1 to disable without removing the plugin.

-

Tailscale

-

Full tab completion for the tailscale CLI is provided via -conf.d/tailscale.fish.

-

Done Notifications

-

Desktop notifications fire when a command takes longer than 10 -seconds and the terminal window is not focused. Configured via fish -universal variables:

-
__done_min_cmd_duration          10000 ms
-__done_notification_urgency_level  low
-

Scrollback -History

-

When running inside Kitty, closing a shell session via exit saves a -timestamped scrollback snapshot to SCROLLBACK_HISTORY_DIR. Files are -named:

-
scrollback_YYYY-MM-DD_HH-MM-SS.log
-

The paru and yay wrappers (auto-generated in ~/.local/bin/) run the -command inside a PTY via script(1) so download progress bars are -preserved on screen, then render the captured terminal animation down to -a clean static log via scripts/clean_progress_log.py (a small -terminal-screen emulator that replays cursor movements, collapses -repainted progress frames to their final state, and preserves ANSI -color). If python3 is unavailable the wrapper falls back to dropping -only the script(1) header/footer. Output is saved to:

-
paru_YYYY-MM-DD_HH-MM-SS.log
-yay_YYYY-MM-DD_HH-MM-SS.log
-

Before pruning, _scrollback_prune_junk silently removes empty files, -files with only a single meaningful line (e.g. bare [exited] captures), -and Kitty tab-rename prompt captures. Use exit --no-log (or exit -n) to -skip capture.

-
- - diff --git a/docs/html/6-2-path-setup.html b/docs/html/6-2-path-setup.html deleted file mode 100644 index 63dc20a..0000000 --- a/docs/html/6-2-path-setup.html +++ /dev/null @@ -1,506 +0,0 @@ - - - - - - - - 2. PATH SETUP - - - - - - -

2. PATH SETUP

-

Directories prepended to PATH in this order (first wins):

-
~/.local/bin              Standard user-local executables
-~/Applications            User-installed standalone apps
-~/scripts                 Personal shell scripts
-~/bin                     Cargo binaries (appended — lowest priority)
-$BUN_INSTALL/bin          Bun runtime and global packages
-$NPM_CONFIG_PREFIX/bin    Global npm packages
-~/.lmstudio/bin           LM Studio CLI
-~/.resend/bin             Resend CLI
-~/.fzf/bin                fzf binary (git-installed)
-

Cargo binaries are intentionally appended (lowest priority) to avoid -shadowing system-installed Rust tools.

-
- - diff --git a/docs/html/7-3-key-bindings.html b/docs/html/7-3-key-bindings.html deleted file mode 100644 index f32a7cf..0000000 --- a/docs/html/7-3-key-bindings.html +++ /dev/null @@ -1,538 +0,0 @@ - - - - - - - - 3. KEY BINDINGS - - - - - - -

3. KEY BINDINGS

-

The shell uses Vi key bindings (fish_vi_key_bindings). All custom -bindings are active in Insert, Normal, and Visual modes unless -noted.

-
Binding         Action
-─────────────────────────────────────────────────────────────────────
-Ctrl+G          Insert the head of the previous command's last path
-                argument. Equivalent to !$:h in Bash.
-                Example: previous = "cd /usr/local/bin"
-                         Ctrl+G inserts "/usr/local"
-
-Ctrl+F          Interactive history substitution. Type old/new then
-                press Ctrl+F to apply s/old/new/ to the previous
-                command. Equivalent to !!:s/old/new/ in Bash.
-                Example: previous = "echo this is a test"
-                         type "this is/that was", press Ctrl+F
-                         result = "echo that was a test"
-
-Ctrl+Alt+U      Strip the first token of the current command line,
-                leaving arguments in place with the cursor at the
-                start. Useful for quickly retyping the command.
-                Example: "mkdir new_folder" -> " new_folder"
-
-Ctrl+Alt+=      Evaluate the current command line buffer with
-                Qalculate! (qalc) and print the result inline.
-                Requires qalc to be installed.
-                Example: type "150 * 1.08", press Ctrl+Alt+=
-                         prints 162
-
-Ctrl+Enter      Smart execute: runs commands instantly without
-                pressing Enter a second time for certain fast-path
-                commands (speedtest-fast, etc.).
-
-@@              FZF inline picker. Type @@ anywhere on the command
-                line to open an fzf picker and insert a selection
-                at the cursor position.
-

FZF Bindings (bundled -from PatrickF1/fzf.fish)

-
Ctrl+R          Search command history
-Ctrl+Alt+F      Search git-tracked files
-Ctrl+Alt+L      Search git log
-Ctrl+Alt+S      Search git status
-Ctrl+V          Search shell variables
-Ctrl+Alt+P      Search running processes
-
- - diff --git a/docs/html/8-4-abbreviations.html b/docs/html/8-4-abbreviations.html deleted file mode 100644 index 75ec2e8..0000000 --- a/docs/html/8-4-abbreviations.html +++ /dev/null @@ -1,641 +0,0 @@ - - - - - - - - 4. ABBREVIATIONS - - - - - - -

4. ABBREVIATIONS

-

Abbreviations expand when you press Space or Enter. They are -terminal-aware: some expand differently in Kitty vs WezTerm vs other -terminals.

-

4.1 Editors

-
n / nv / neovim    nvim
-e                  edit
-se                 sudoedit
-k                  kate
-editt              Open new tab with nvim (terminal-aware)
-cdnv               cd ~/.config/nvim
-cdnvn              cd ~/.config/nvim; nvim
-

4.2 Navigation and -Listing

-
l                  ls
-lS                 lss       (sort by size)
-lsR                lsr       (sort by time, oldest first)
-lX                 lx        (sort by extension)
-lT                 lt        (tree, depth 2)
-lsT                lstree    (full recursive tree)
-lzd                ld        (lazydocker)
-cdi                zi        (interactive zoxide picker)
-

4.3 Git

-
g                  git
-lg                 lazygit
-gitig / git-ignore gi        (generate .gitignore)
-

4.4 -Terminal Windows, Tabs, and Panes

-

These abbreviations control the terminal emulator. Each has a Kitty -variant and a WezTerm variant; the correct one is inserted based on -$TERM or $TERM_PROGRAM.

-
:w          New OS window
-:wv         Split pane horizontally (new pane below)
-:wh         Split pane vertically (new pane to the right)
-:wo         Detach current window to its own OS window
-:wot        Move current pane to a new tab
-:t          New tab
-:tl         Set tab title
-:tw         Set window title
-:twk        Rename workspace (WezTerm only)
-:tp         Focus previous tab
-:tn         Focus next tab
-:q          Close current pane/window
-:Q          Close current tab
-:sw         spwin (spawn new OS window)
-

Quick-navigate shortcuts open windows/tabs/panes with preset working -dirs:

-
:tgk    New tab at ~/.config/kitty
-:tgn    New tab at ~/.config/nvim
-:tgf    New tab at ~/.config/fish
-:tgh    New tab at ~
-:tgcz   New tab at chezmoi source dir
-:tgcm   New tab at chezmoi source dir
-:tgp    New tab at ~/projects
-:tgr    New tab at / (root)
-

Prefixes :wg* and :wvg* / :whg* open OS windows or splits to the same -set of dirs, respectively.

-

Prefixes :cd* open tabs with a quick cd shortcut:

-
:cdn    cd ~/.config/nvim
-:cdf    cd ~/.config/fish
-:cdh    cd ~
-:cdcz   cd to chezmoi source
-:cdp    cd ~/projects
-

Appending n to any :cd* abbreviation also runs nvim after changing -dir.

-

4.5 Chezmoi

-
cm / cme / cmi / cmap / cmad / cmrm / cmcd /
-cz / cze / czi / czap / czad / czrm / czcd
-
-cm / cz          chezmoi
-cmcd / czcd      chezmoi cd
-cme / cze        chezmoi edit
-cmad / czad      chezmoi add
-cmap / czap      chezmoi apply
-cmrm / cmf / czrm / czf    chezmoi forget
-cmi / czi        chezmoi init
-

4.6 Docker

-
dcl         docker context use default
-dcls        docker context ls
-lzd         ld (lazydocker)
-

4.7 Systemctl

-
sc          systemctl
-ssc         sudo systemctl
-scu         systemctl --user
-st          systemctl status
-scs         sudo systemctl start
-scr         sudo systemctl restart
-ssct        sudo systemctl start
-sscs        sudo systemctl stop
-sscr        sudo systemctl restart
-

4.8 AI Assistants

-
ag          agy
-ag.         agy .
-v           antigravity-ide
-s           wezterm ssh (WezTerm only)
-

4.9 History -Expansion

-

These are implemented as keybinding helpers, but can also be -typed:

-
!^          Expand to first argument of previous command
-!*          Expand to all arguments of previous command
-typo_sub    Interactive typo substitution (Ctrl+F)
-bang_string !string expansion
-bang_search !?string search
-bang_minus_n  !-n  (nth-previous command)
-

4.10 Miscellaneous

-
/exit       exit
-:q          Close pane (alias for terminal close)
-:Q          Close tab
-sudu        sudo -s
-kt          kitty (Kitty only)
-c           cat
-speedtest-fast  fast-cli
-bl          bd list
-bs          bd sync
-bC          bd create --title
-bsh         bd show
-lb          lazybeads
-

4.11 Shell Aliases

-

These aliases are defined in conf.d/tricks.fish via alias (which -creates Fish functions). They are active in all interactive -sessions.

- -
..      cd ..
-...     cd ../..
-....    cd ../../..
-.....   cd ../../../..
-......  cd ../../../../..
-

Color Overrides

-

Force color output for common tools:

-
grep    grep --color=auto
-fgrep   fgrep --color=auto
-egrep   egrep --color=auto
-dir     dir --color=auto
-vdir    vdir --color=auto
-

Safety Wrappers

-

Add -i (interactive confirmation) to destructive commands:

-
cp      cp -i
-mv      mv -i
-

Archives and -Networking

-
tarnow  tar -acf              Create compressed archive (auto-detects format)
-untar   tar -zxvf             Extract a gzip-compressed archive
-wget    wget -c               Resume interrupted downloads by default
-tb      nc termbin.com 9999   Pipe content to termbin.com for quick sharing
-

System Logs

-
jctl    journalctl -p 3 -xb   Show priority-3 (error) journal entries
-                                from the current boot
-
- - diff --git a/docs/html/9-5-functions-reference.html b/docs/html/9-5-functions-reference.html deleted file mode 100644 index 1a556e1..0000000 --- a/docs/html/9-5-functions-reference.html +++ /dev/null @@ -1,1372 +0,0 @@ - - - - - - - - 5. FUNCTIONS REFERENCE - - - - - - -

5. FUNCTIONS -REFERENCE

-

5.1 File and -Directory

-

cat

-
Synopsis:  cat [args...]
-Wraps bat for files with syntax highlighting and line numbers.
-Passes directories to ls. Falls back to /usr/bin/cat.
-
-cat README.md
-cat ~/projects/myapp
-

copy

-
Synopsis:  copy <source> <dest>
-Wraps cp, stripping trailing slashes from source directories to
-prevent unintended nesting inside the destination.
-
-copy ./mydir/ ~/backup    # copies mydir INTO backup, not backup/mydir/
-

du

-
Synopsis:  du [--disk|--dir|--dua] [args...]
-Smart disk-usage dispatcher:
-  --disk  force duf  (disk-level free/used overview)
-  --dir   force dust (per-directory tree breakdown)
-  --dua   force dua  (fast space analyzer)
-Without flags, routes to the most appropriate tool by context.
-
-du ~/Downloads
-du --disk
-

dusize

-
Synopsis:  dusize [dir]
-Human-readable disk usage for a directory via du -sh. Defaults to cwd.
-
-dusize ~/Videos
-

lD

-
Synopsis:  lD [args...]
-Lists directories only in long format with icons. Uses eza, falls back
-to lsd, then system ls.
-
-lD ~/projects
-

ls

-
Synopsis:  ls [args...]
-Lists files in long format with icons and hyperlinks. Uses eza, falls
-back to lsd, then system ls.
-
-ls
-ls -a ~/projects
-

lsr

-
Synopsis:  lsr [args...]
-Lists files sorted by modification time, oldest first. Uses eza.
-

lss

-
Synopsis:  lss [args...]
-Lists files sorted by size with gradient color scaling. Uses eza.
-

lstree

-
Synopsis:  lstree [args...]
-Full recursive tree view with icons. Uses eza.
-
-lstree ~/projects/myapp
-

lt

-
Synopsis:  lt [args...]
-Tree view limited to depth 2 with icons. Uses eza.
-
-lt ~/projects
-

ltr

-
Synopsis:  ltr [args...]
-Lists files sorted by modification time, oldest first, long format with
-age-based gradient scaling. Uses eza.
-

lx

-
Synopsis:  lx [args...]
-Lists files sorted by extension, long format. Uses eza.
-

mkdir

-
Synopsis:  mkdir [args...]
-Interactive mkdir that prints a tree of created directories.
-Falls back to mkdir -p silently.
-
-mkdir ~/projects/myapp/src
-

mkcd

-
Synopsis:  mkcd [-s] <dir>
-Creates a directory (including parents) and cd into it. Prints a tree
-of created dirs by default; -s/--silent suppresses output.
-
-mkcd ~/projects/newapp/src
-

poke

-
Synopsis:  poke <file> [file...]
-Creates files via touch, automatically creating any missing parent
-directories first.
-
-poke ~/projects/new/src/main.fish
-

rm

-
Synopsis:  rm [-e [opts] | -S | args...]
-Safe rm wrapper routing to trash:
-
-  (no args)   List current trash contents
-  -e/--empty  Empty the trash (pass options to trash-empty)
-  -S/--secure Permanently delete via rm -rf + fstrim (irreversible)
-  -r/-R/--recursive  Move to trash
-  <paths>     Move to trash (safe delete)
-
-Falls back to /usr/bin/rm when trash is unavailable.
-
-rm file.txt           # moves to trash
-rm -e                 # empty trash
-rm -S sensitive.pem   # permanent delete
-

rg

-
Synopsis:  rg [args...]
-In Kitty, wraps ripgrep with --hyperlink-format=kitty so search
-results are clickable file links in the terminal. Falls back to
-system rg in any other terminal. All other arguments pass through
-unchanged.
-
-rg "fish_greeting" ~/.config/fish/
-rg -l "TODO" ~/projects/myapp
-

scrub

-
Synopsis:  scrub [-a] [-d] [-h]
-Recursively removes OS metadata, editor artifacts, compiler output,
-and dev caches using fd.
-
-  -a/--aggressive  Also removes node_modules, logs, .cache, IDE dirs,
-                   AI session artifacts
-  -d/--dry-run     Print what would be removed without deleting
-
-scrub
-scrub -a
-scrub -d
-
-

5.2 Navigation

-

cdi

-
Synopsis:  cdi [query]
-Interactive directory picker combining zoxide frecency with fzf.
-Equivalent to zi.
-
-cdi myproject
-

clone

-
Synopsis:  clone [args...]
-Clone a git repository into a new Kitty window. Kitty-only.
-
-clone https://github.com/user/repo.git
-

clonet

-
Synopsis:  clonet [args...]
-Clone a git repository into a new Kitty tab. Kitty-only.
-
-clonet https://github.com/user/repo.git
-
-

5.3 Editors and -Viewers

-

edit

-
Synopsis:  edit [-V|-t] [-e EDITOR] [-c] [-x TEXT] [-n] [-v|-s] [FILE...]
-
-Opens files in a text editor, choosing a terminal or GUI editor and
-resolving a rich chain of fallbacks. With no --visual/--terminal flag the
-mode is auto-detected: interactive terminals use the terminal editor
-($EDITOR), while detached invocations (e.g. desktop shortcuts) use the GUI
-editor ($VISUAL). Clipboard contents and literal strings can be opened as
-throwaway temp files. Editor output is suppressed unless --verbose.
-
-GUI fallback chain:      zed → antigravity-ide → code → kate → kwrite →
-                         gnome-text-editor → gedit
-Terminal fallback chain: nvim → vim → micro → nano → vi
-
-Options:
-  -V, --visual      Force the GUI editor ($VISUAL or fallbacks)
-  -t, --terminal    Force the terminal editor ($EDITOR or fallbacks)
-  -e, --editor=X    Use a specific editor binary X
-  -c, --clipboard   Open the clipboard contents (as a temp file)
-  -x, --text=STR    Open STR as the contents of a new temp file
-  -n, --new         Force a new window/instance (best-effort)
-  -v, --verbose     Print the launch command and editor output
-  -s, --silent      Suppress all output, including the editor's
-  -h, --help        Show this help message
-
-edit ~/.config/fish/config.fish
-edit --visual notes.txt
-edit --terminal --new todo.md
-edit --editor=code --clipboard
-edit --text="hello world"
-

fc

-
Synopsis:  fc [command_prefix]
-Edit the last shell command (or one matching a prefix) in $EDITOR,
-then execute the result. Bash-style fc behaviour.
-
-fc
-fc git
-

less

-
Synopsis:  less [args...]
-Pager wrapper with fallback chain: $PAGER -> ov -> less -> more -> cat.
-
-less /var/log/syslog
-

rawfish

-
Synopsis:  rawfish [args...]
-Launches Fish with NO_TMUX=1, bypassing any tmux auto-attach logic.
-Useful when you need a clean shell without session management.
-

view

-
Synopsis:  view [args...]
-Opens files in nvim read-only mode (-R). Falls back to less.
-
-view /etc/fstab
-
-

5.4 Git and -Version Control

-

auto-pull

-
Synopsis:  auto-pull [list]
-           auto-pull add [PATH]
-           auto-pull remove <NAME|PATH>
-           auto-pull status
-
-Manages the registry of repositories that are background fast-forwarded
-when you enter them (see "Auto-pull fast-forward" under the C2 component
-reference). The fish-config repo is always covered as a baseline. The
-registry is machine-local at `$__fish_user_dots_path/auto-pull.list` (defaults
-to `~/.config/.user-dots/fish/auto-pull.list`), one absolute path per line,
-and is never committed. Registry management works
-even when C2 auto-execution is disabled; only the background sync is gated.
-
-  list               Show registered repos (default)
-  add [PATH]         Register PATH's git root (default: current repo)
-  remove <NAME|PATH> Unregister by basename or exact path
-  status             Show enabled/disabled state, repo count, list path
-
-cd ~/src/qmk_firmware; and auto-pull add
-auto-pull add ~/work/api
-auto-pull list
-auto-pull remove qmk_firmware
-

branch

-
Synopsis:  branch <branch_name>
-Switches to a local branch, or creates it if it does not exist.
-
-branch feature/new-ui
-

gi

-
Synopsis:  gi [-h] [-b] [-p] [-s] [-l] [targets...]
-Generates .gitignore content from the gitignore.io API with MD5-based
-deduplication (patterns already present are not re-appended).
-
-  -b/--boilerplate  Append generic boilerplate first
-  -p/--prompt       Prompt interactively for targets
-  -s/--stdout       Print to stdout instead of appending to .gitignore
-  -l/--list         List all available targets
-  targets           Comma-separated or space-separated target names
-
-gi python,venv
-gi -b -p
-gi -s node > .gitignore
-

git-clean

-
Synopsis:  git-clean [-f]
-Fetches and prunes the remote, fast-forwards the current branch, then
-deletes local branches whose remote tracking branch has been deleted.
-Switches to main/master automatically if the current branch is orphaned.
-
-  -f/--force  Force-delete unmerged branches too
-
-git-clean
-git-clean --force
-

gitup

-
Synopsis:  gitup [args...]
-Fetches updates from the remote and shows git status. Extra args are
-forwarded to git fetch.
-
-gitup
-gitup --all
-

gitui

-
Synopsis:  gitui [args...]
-Launches gitui with the Catppuccin Frappe theme pre-applied.
-

hist

-
Synopsis:  hist
-Searches shell history with fzf, inserts the selection into the command
-line, and copies it to the clipboard via wl-copy.
-
-

5.5 Package -Management

-

pkg

-
Synopsis:  pkg [-h] [-i|-u] <package> [package...]
-Installs or removes packages using the detected system package manager.
-Supports: paru, yay, pacman, apt, dnf, zypper, yum, brew, pkg.
-
-  (no flag)    Auto mode: installs missing packages, removes installed ones
-  -i/--install  Force install
-  -u/--uninstall  Force uninstall
-
-pkg firefox             # auto: install if missing, remove if present
-pkg -i ripgrep fd       # force install
-pkg -u cowsay           # force uninstall
-
-The package-installed check uses the correct query for each PM:
-  pacman/paru/yay  pacman -Qi
-  apt              dpkg -s
-  dnf/zypper/yum   rpm -q
-  brew             brew list
-  pkg              pkg info
- -
Synopsis:  search [args...]
-Interactive AUR package search and install via paru or yay.
-Arch Linux only.
-
-search neovim
-

upgrade

-
Synopsis:  upgrade
-Full system upgrade via paru -Syu --noconfirm or yay -Syu --noconfirm.
-Arch Linux only.
-

cleanup

-
Synopsis:  cleanup
-Lists and removes orphan packages via pacman, logging their names to
-~/.removed_orphans. Arch Linux only.
-

parur

-
Synopsis:  parur
-Opens an fzf picker of all installed packages (with pacman -Qi previews),
-then removes the selected packages via paru or yay. Arch Linux only.
-
-parur
-
-

5.6 Dependency -Management

-

fish-deps

-
Synopsis:  fish-deps [status|install|update|sync]
-Unified command for managing all tools this configuration depends on.
-
-  status   (default) Show installed/missing status grouped by tier
-  install  Interactively install each missing dependency
-  update   Update all installed dependencies
-  sync     Install missing deps, then update all
-
-Install method priority (highest to lowest):
-  1. git+cargo source build (fish shell itself)
-  2. cargo (Rust tools — gets latest crate version)
-  3. system PM (paru/apt/brew/etc.)
-  4. git clone (fzf)
-  5. curl installer (starship, fisher, uv)
-
-When multiple methods are available you are prompted to choose.
-
-Dependencies are grouped into three tiers:
-
-  Required      fish, fzf, zoxide
-  Integrations  wakatime, tailscale
-  Recommended   cargo, starship, uv, direnv, paru, yay, eza, lsd, bat,
-                btop, dust, duf, prettyping, ov, ripgrep, lazygit,
-                lazydocker, trash, kitty, wezterm, python3, yt-dlp
-
-fish-deps
-fish-deps install
-fish-deps update
-fish-deps sync
-

check_fish_deps

-
Synopsis:  check_fish_deps
-Backwards-compatibility alias for `fish-deps status`.
-
-

5.7 System and -Monitoring

-

top

-
Synopsis:  top [args...]
-Launches btop as a modern resource monitor. Falls back to system top.
-

swapstat

-
Synopsis:  swapstat
-Displays a colorized memory report: kernel swappiness, zRAM compression
-ratio, zRAM device details, and active swap priorities.
-

sbver

-
Synopsis:  sbver [--brief]
-Verifies Secure Boot signatures on all EFI binaries tracked by sbctl.
-Color-codes results: green checkmark (verified), red X (unsigned).
-Prints a pass/fail summary.
-
-  --brief  Suppress per-file output, show only the summary
-
-sbver
-sbver --brief
-

ports

-
Synopsis:  ports
-Lists active TCP listeners with lsof, showing port/address without
-hostname resolution.
-

screensleep

-
Synopsis:  screensleep
-Turns off the display via KDE PowerDevil's "Turn Off Screen" action,
-invoked through busctl.
-

lock

-
Synopsis:  lock
-Locks the current desktop session using loginctl lock-session.
-

sudo-toggle

-
Synopsis:  sudo-toggle
-Toggles the sudo NOPASSWD rule on/off via /etc/sudoers.d/nofail-toggle.
-Useful for automated tasks that would otherwise require password entry.
-

limine-edit

-
Synopsis:  limine-edit
-Opens /boot/limine.conf in sudoedit, then automatically re-enrolls the
-config hash, runs CachyOS boot hooks, and re-signs Secure Boot files.
-Combines the edit and sign steps into a single command.
-
-

5.8 Terminal -Management

-

tab

-
Synopsis:  tab [args...]
-Opens a new tab in Kitty (kitty @ launch --type=tab), WezTerm
-(wezterm cli spawn), or Konsole. Uses current working directory,
-or $cdto if set.
-
-tab
-

split

-
Synopsis:  split [-h|-v] [command...]
-Opens a new pane in Kitty or WezTerm, optionally running a command.
-
-  -h/--horizontal  (default) Split below
-  -v/--vertical    Split to the right
-
-split
-split -v nvim README.md
-

spwin

-
Synopsis:  spwin [args...]
-Spawns a new terminal OS window in Kitty (via spawn-window.sh or
-kitty @ launch --type=os-window) or WezTerm (wezterm cli spawn --new-window).
-

detach

-
Synopsis:  detach [-h] [--version] <command> [args...]
-Runs a command fully detached via nohup with stdout/stderr discarded.
-The command survives the current session.
-
-detach rsync -a ./data remote:/backup/
-

bkg

-
Synopsis:  bkg <command> [args...]
-Launches a command in the background via nohup with output discarded.
-Simpler than detach; no version flag.
-
-bkg firefox
-

ssh

-
Synopsis:  ssh [args...]
-In Kitty, wraps ssh with kitten ssh for better terminal integration
-(multiplexing, copy/paste support). Falls back to system ssh elsewhere.
-
-ssh user@host
-
-

5.9 Clipboard

-

y

-
Synopsis:  y [text...]
-Copies text to the clipboard via wl-copy (Wayland) or xclip (X11).
-Reads from stdin if no arguments given.
-
-y "hello world"
-ls | y
-cat file.txt | y
-

p

-
Synopsis:  p [args...]
-Outputs clipboard contents to stdout.
-
-p | grep foo
-p > file.txt
-

paste

-
Alias for p. Identical behaviour.
-
-

5.10 Network

-

gip

-
Synopsis:  gip
-Fetches and prints both the public IPv4 and IPv6 address via
-icanhazip.com.
-

gip4

-
Synopsis:  gip4
-Fetches and prints the public IPv4 address.
-

gip6

-
Synopsis:  gip6
-Fetches and prints the public IPv6 address. Returns 1 if IPv6 is
-unavailable.
-

ping

-
Synopsis:  ping [args...]
-Wraps prettyping with --nolegend. Pass --legend to show the legend.
-Falls back to system ping.
-
-ping google.com
-

qr

-
Synopsis:  qr [text...]
-Generates a UTF-8 QR code from text or stdin. Uses qrencode locally;
-falls back to the qrenco.de API.
-
-qr "https://example.com"
-echo "https://example.com" | qr
-
-

5.11 Pager and -Logging

-

logs

-
Synopsis:  logs [-c <category>]
-Interactively browses terminal log files sorted newest-first using fzf.
-
-  -c/--category  Filter to: scrollback, paru, or yay
-
-Keybindings inside the fzf browser:
-  Enter    Open in $PAGER
-  Ctrl+E   Open in $EDITOR
-  Ctrl+D   Delete (with confirmation)
-  ?        Toggle keybind help overlay
-
-Paru and yay logs open in ov with syntax highlighting and sticky section
-headers. Scrollback logs open in ov with per-command sticky prompt headers
-based on OSC 133 markers.
-
-logs
-logs -c paru
-logs -c scrollback
-

smart_exit

-
Synopsis:  smart_exit [-n]
-Closes the shell session. In Kitty, captures the terminal scrollback to
-a timestamped log file in $SCROLLBACK_HISTORY_DIR before exiting.
-Automatically prunes the oldest logs when the count exceeds
-$SCROLLBACK_HISTORY_MAX_FILES.
-
-  -n/--no-log  Exit without saving a scrollback log
-
-The exit builtin is wired to smart_exit for interactive sessions.
-Typing exit or Ctrl+D behaves identically to smart_exit.
-
-smart_exit
-smart_exit --no-log
-
-

5.12 AI and -Developer Tools

-

agy

-
Synopsis:  agy [args...]
-Wrapper for the agy Antigravity AI CLI. Before launching, delegates to
-agents-init --agents to ensure AGENTS/ is scaffolded and CLAUDE.md is
-symlinked to AGENTS/AGENTS.md in the current project, then forwards all
-arguments verbatim to the real agy binary. Command shadow (C1): when
-__fish_config_op_aliases (or the master) is disabled, the call is
-passed through to the real agy binary unchanged.
-
-agy chat
-agy resume
-

antigravity-ide

-
Synopsis:  antigravity-ide [args...]
-Runs the antigravity-ide editor with warnings filtered.
-

agents-init

-
Synopsis:  agents-init [--agents | --plugins]
-Scaffold an AGENTS/ sub-repository for tracking agent specs, plans, specs,
-and dev logs. Creates AGENTS/ as a standalone git repo, moves any existing
-AGENTS.md into it, and replaces it with a relative symlink (plus
-CLAUDE.md -> AGENTS/AGENTS.md so Claude Code picks up the shared agent
-instructions). Consolidates plans/ and specs/ directly under AGENTS/
-(merging any legacy docs/plans, docs/superpowers/plans, or old
-AGENTS/plugins/ locations into the canonical AGENTS/<tgt>), creates
-AGENTS/devlogs/, and wires docs/superpowers/{plans,specs} symlinks back to
-them. Adds managed paths to .gitignore and auto-commits every change inside
-the AGENTS/ sub-repo; pulls first when the sub-repo has an upstream.
-Fully idempotent: a second run produces no output and no new commits.
-Flags: --agents re-runs only the AGENTS.md / symlink step; --plugins
-re-runs only the plans/specs/devlogs wiring step. Called automatically by
-the claude and agy wrappers on every invocation.
-
-Structure versioning: each AGENTS/ repo carries a self-contained version
-bumper. AGENTS/.version holds MAJOR.MINOR.PATCH (seeded 1.0.0). Committed
-git hooks under AGENTS/.agents-tools/ (wired via core.hooksPath) bump it on
-every commit: MINOR (resetting PATCH) when the tracked directory set
-changes, PATCH otherwise; MAJOR is manual-only. A prepare-commit-msg hook
-appends "(vX.Y.Z)" to the commit subject. Downstream tooling can read
-AGENTS/.version - a changed MINOR field signals a structure change. Because
-core.hooksPath is a single setting, the local override would otherwise
-shadow your global hooks; after bumping the version, each shim chains
-(execs) to the global/system core.hooksPath hook of the same name so global
-pre-commit / prepare-commit-msg hooks (e.g. ggshield, Git LFS) still run.
-The script and hooks are shipped from scripts/agents-tools/ and refreshed
-when their version marker is stale.
-
-agents-init
-agents-init --agents
-agents-init --plugins
-

claude

-
Synopsis:  claude [args...]
-Wrapper for the claude CLI. Before launching, delegates to agents-init
---agents to ensure AGENTS/ is scaffolded and CLAUDE.md is symlinked to
-AGENTS/AGENTS.md in the current project, then forwards all arguments
-verbatim to the real claude binary. Command shadow (C1): when
-__fish_config_op_aliases (or the master) is disabled, the call is
-passed through to the real claude binary unchanged.
-
-claude
-claude --resume
-

claude-docs

-
Synopsis:  claude-docs
-Invokes Claude Code to analyze recent repository changes and update
-README.md, ensuring all documented features and examples are accurate.
-

claude-pr

-
Synopsis:  claude-pr
-Invokes Claude Code to run the full PR workflow: create branch,
-conventional commit, verification, push, and open a PR with a manual
-verification checklist.
-

qc

-
Synopsis:  qc [prompt...]
-Quick-chat wrapper around the aichat LLM CLI that defaults to the "cli"
-role - a system prompt tuned for concise, terminal-friendly output. On
-first use it installs the bundled role by symlinking
-scripts/cli-agent.md to $XDG_CONFIG_HOME/aichat/roles/cli.md (creating
-the directory if needed). Inherits every aichat flag and tab completion
-(--wraps aichat); passing --role/-r overrides the default role, so qc
-forwards to aichat unchanged. The function is only defined when aichat
-is installed. Run qc --help for aichat's full flag reference with the
-command name rewritten to qc.
-
-qc "how do I list open ports on linux?"
-qc -m ollama:llama3 "explain this error"
-qc --role coder "refactor this function"
-

superpowers

-
Synopsis:  superpowers [on|off] [-g]
-Enables or disables the Superpowers plugin for Antigravity and Claude
-Code at workspace/project scope (default) or user scope (-g/--global).
-
-superpowers on
-superpowers off -g
-
-

5.13 Media and -Utilities

-

dng2avif

-
Synopsis:  dng2avif [-i <file>] [-o <file>] [-q <n>] [-s <n>] [input.dng]
-Converts a DNG raw image to a 10-bit HDR AVIF using an ImageMagick,
-ffmpeg, avifenc pipeline with metadata sync via exiftool.
-
-  -i/--input    Input file (or positional arg)
-  -o/--output   Output file (default: same name, .avif extension)
-  -q/--quality  Quality 0-100 (default 92)
-  -s/--speed    Encoding speed 0-10 (default 3)
-
-dng2avif photo.dng
-dng2avif -q 85 -s 5 -i shot.dng -o out.avif
-

steam-dl

-
Synopsis:  steam-dl
-Launches Steam under systemd-inhibit, preventing the system from going
-idle or sleeping while a download is in progress.
-

spark

-
Synopsis:  spark [--min=<n>] [--max=<n>] [numbers...]
-Renders a Unicode sparkline bar chart for a sequence of numbers.
-Reads from stdin if no numbers are given.
-
-spark 1 1 2 5 14 42
-echo "3 7 2 9 1" | spark
-

yt-dlp

-
Synopsis:  yt-dlp [args...] URL [URL...]
-Wraps yt-dlp, prepending sane defaults: --sponsorblock-remove all,
---embed-subs, --embed-metadata, and --embed-thumbnail. Each default
-is suppressed when you already pass that flag, its alias, or its
-negation (e.g. --no-embed-thumbnail drops the thumbnail default;
---no-sponsorblock or your own --sponsorblock-remove drops ours). All
-other arguments pass through unchanged, and --help falls through to
-real yt-dlp. Opinionated component (C1 aliases); when disabled it
-passes straight through to the system yt-dlp.
-
-yt-dlp dQw4w9WgXcQ
-yt-dlp --no-embed-thumbnail dQw4w9WgXcQ
-
-

5.14 Miscellaneous

-

config-help

-
Synopsis:  config-help [SECTION]
-           config-help [SECTION] --html
-           config-help [SECTION] --man
-           config-help -h | --help
-
-Opens the offline fish shell configuration manual. Without flags, opens
-the Markdown source in the best available pager (ov > bat > man > less >
-cat). If SECTION is given, jumps to the first heading matching that
-keyword (case-insensitive; checks fish-config.index aliases first).
-
-Flags:
-  --html / -w   Open docs/html/index.html in the default browser.
-                If SECTION is given, opens at the matching anchor.
-                Detects the browser via xdg-mime x-scheme-handler/https,
-                then known binaries, then xdg-open as last resort.
-                Respects $fish_help_browser and $BROWSER.
-  --man  / -m   Open docs/fish-config.1 via man -l directly.
-                If SECTION is given, jumps to the nearest match.
-  --help / -h   Print usage and navigation key reference.
-
-config-help keybindings
-config-help pkg
-config-help --html
-config-help pkg --html
-config-help --man
-config-help pkg --man
-
-Also available as: help config [SECTION] [FLAGS]
-

open-url

-
Synopsis:  open-url [-s|--silent] [-v|--verbose] <url>
-           open-url -h | --help
-
-Opens a URL or file:// URI in the best available graphical web browser,
-backgrounded so it never blocks the terminal. Resolves a real browser
-binary rather than deferring to xdg-open, whose MIME dispatch can hand
-local text/html files to non-browser apps (e.g. ebook readers).
-
-Silent by default: prints nothing on success (errors always go to
-stderr). Pass --verbose / -v to report which browser is launched;
---silent / -s is accepted for explicitness.
-
-Resolution order:
-  1. $fish_help_browser  (explicit override)
-  2. $BROWSER            (validated; errors if not a command)
-  3. xdg-mime default handler for x-scheme-handler/https
-  4. First known browser binary found in a built-in list
-  5. xdg-open            (last resort)
-
-open-url https://git.rootiest.dev/rootiest/fish-config
-open-url "file://$HOME/.config/fish/docs/html/index.html"
-
-Used internally by config-help --html.
-
-Typo abbreviation: url-open (expands to open-url on space/enter).
-

repo-open

-
Synopsis:  repo-open [-p|--print] [-r|--root]
-           repo-open -h | --help
-
-Opens the web page for the current repository's `origin` remote in a
-browser (via open-url). Deep-links to the current branch when it exists
-on the remote — falling back to the remote's default branch (main/master)
-otherwise — and to the current sub-directory when run below the repo root.
-
-The remote URL is normalized from HTTPS and SSH/scp forms
-(git@host:owner/repo.git, ssh://…, https://…). The web path layout is
-provider-specific; the provider is resolved in order:
-
-  1. git config browse.provider   (per-repo or --global override)
-  2. Hostname heuristic           (github / gitlab / gitea / bitbucket;
-                                    codeberg → gitea)
-  3. Default: github-style layout
-
-Self-hosted hosts the heuristic can't classify (a Gitea/GitLab instance
-on a custom domain) need a one-time override:
-
-  git config browse.provider gitea
-
-Flags:
-  --print / -p   Print the resolved URL instead of opening it.
-  --root  / -r   Ignore the current sub-directory; link to the repo root.
-  --help  / -h   Show usage.
-
-repo-open
-repo-open --print
-repo-open --root
-
-Typo abbreviation: open-repo (expands to repo-open on space/enter).
-

config-update

-
Synopsis:  config-update [-h] [-n] [-f]
-
-Pulls the latest fish configuration from the upstream repository
-(https://git.rootiest.dev/rootiest/fish-config.git) into ~/.config/fish.
-The remote URL is hard-coded, so this works on fresh clones with no git
-remote configured. All git output is suppressed; colored messages report
-fetch and merge status. After a successful pull, run `exec fish` to
-reload.
-
-Flags:
-  --dry-run / -n   Fetch and show available commits without applying them.
-  --force  / -f    Stash local changes, pull, then restore the stash.
-  --help   / -h    Show usage.
-
-config-update
-config-update --dry-run
-config-update --force
-

config-settings

-
Synopsis:  config-settings [-h]
-
-Opens an interactive TUI for managing fish configuration settings across
-four pages, without having to type or remember variable names. Tab cycles
-forward through the pages; Shift-Tab cycles backward.
-
-  Universal — opinionated category toggles (C1–C6) + master, persistent (set -U)
-  Session   — the same toggles, current shell only (set -g)
-  Sponge    — sponge history-scrubbing settings: delay, successful exit
-              codes, purge-only-on-exit, allow-previously-successful, and
-              extra sensitive variable-name tokens
-  Paths     — scrollback log directory, scrollback max files, the
-              user-dots path, and the user-dots convenience symlink toggle
-              (Dots link)
-
-Toggle rows use ← → (or h/l) along an OFF ← DEFAULT → ON scale; DEFAULT
-erases the variable so the master switch / built-in default applies. Value
-rows (the path/int/list settings on the Sponge and Paths pages) use Enter to
-edit inline; ← / h clears the value back to its default. List rows (e.g.
-Extra secret, OK codes) accept values separated by commas and/or whitespace
-— "A, B", "A,B" and "A B" all yield the same two entries. Changes apply
-immediately. Always available regardless of the __fish_config_opinionated
-master state.
-
-The Sponge and Paths pages always write universal variables — these are
-persistent, set-and-forget settings with no per-session scope. Editing a
-scrollback row updates both the __fish_scrollback_history_* source-of-truth
-variables and the exported SCROLLBACK_HISTORY_* mirrors, so the AUR/tmux/
-zellij log wrappers (which read the exported names) see the change in the
-running session.
-
-The panel adapts to the terminal width automatically, selecting from
-four layout tiers (with a 6-column buffer on each side before stepping
-up to the next tier) and horizontally centering the box. The panel
-redraws within ~0.3 s of a terminal resize with no keypress required.
-
-  COLUMNS >= 90  →  78-wide panel (most detail)
-  COLUMNS >= 86  →  74-wide panel
-  COLUMNS >= 82  →  70-wide panel
-  COLUMNS  < 82  →  52-wide panel (default)
-
-Navigation:
-  ↑ ↓ / k j     Move cursor
-  ← → / h l     Toggle rows: OFF ← DEFAULT → ON
-  ←  / h        Value rows: clear to default
-  Enter         Value rows: edit inline (Sponge / Paths pages)
-  Tab / S-Tab   Next / previous page
-  q / Escape    Exit
-
-Flags:
-  --help / -h   Show usage.
-
-config-settings
-

config-toggle -(deprecated)

-
Deprecated alias for config-settings. Prints a deprecation notice to
-stderr, then delegates all arguments to config-settings.
-
-config-toggle
-

bash

-
Synopsis:  bash [args...]
-Switches to bash, with XDG config applied. On exit, $SHELL is reset
-back to fish.
-

bd-pull

-
Synopsis:  bd-pull <owner/repo>
-Fetches unlinked Gitea issues and creates local Beads entries, updating
-issue titles with the assigned Beads IDs.
-Requires $GITEA_TOKEN and $GITEA_URL to be set.
-
-bd-pull rootiest/fish-config
-

cheat

-
Synopsis:  cheat <topic> [args...]
-Displays a colorized cheatsheet using cheat -c, falls back to tldr,
-then man.
-
-cheat tar
-cheat git
-

cffetch / ffetch

-
Synopsis:  cffetch [args...]  /  ffetch [args...]
-Clears the screen and displays system information via fastfetch with
-the custom config at ~/.fastfetch.jsonc. Falls back to neofetch.
-

dockup

-
Synopsis:  dockup [-h] [directory]
-Pulls latest Docker images, restarts services in the given Docker
-Compose project, and prunes dangling images.
-
-dockup ~/myapp
-

joplin

-
Synopsis:  joplin [args...]
-Runs the Joplin CLI with Node.js deprecation warnings suppressed.
-
-joplin ls
-

ld

-
Synopsis:  ld
-Launches lazydocker targeting the currently active Docker context,
-detected via docker context inspect.
-

replay

-
Synopsis:  replay <commands>
-Runs Bash commands and replays any resulting changes to environment
-variables, aliases, and the working directory back into the current
-Fish session. Useful for sourcing Bash scripts.
-
-replay "source ~/.bashrc"
-replay "export FOO=bar"
-

kitty-logging

-
Synopsis:  kitty-logging [install|uninstall|status|dismiss] [-h]
-
-Manages the Kitty scrollback watcher that powers C5 logging. Ships a
-canonical watcher and symlinks it into the Kitty config directory (so it
-always tracks the source), wiring it into kitty.conf through a
-sentinel-marked managed block. Commenting out any conflicting watcher line
-avoids double-capture.
-
-Commands:
-  install    Symlink the watcher and add the managed block
-  uninstall  Remove the managed block and the watcher symlink
-  status     Show wiring, installed watcher version, and C5 state
-  dismiss    Stop the per-session setup reminder
-
-Runtime capture stays governed by the C5 .logging_disabled sentinel, so
-disabling __fish_config_op_logging makes the watcher inert without
-uninstalling. Install affects new Kitty windows only.
-
-Example:
-  kitty-logging install
-  kitty-logging status
-

tmux-clean

-
Synopsis:  tmux-clean
-Kills all detached (unattached) tmux sessions, leaving attached ones
-running.
-

wake-lock

-
Synopsis:  wake-lock <command> [args...]
-Runs a command under systemd-inhibit, preventing the system from going
-idle or sleeping until the command completes.
-
-wake-lock rsync -avz src/ dest/
-
- - diff --git a/docs/html/index.html b/docs/html/index.html deleted file mode 100644 index 310b707..0000000 --- a/docs/html/index.html +++ /dev/null @@ -1,903 +0,0 @@ - - - - - - - - FISH-CONFIG - - - - - - -
-

FISH-CONFIG

-

Rootiest

-

June 2026

-
- - - - diff --git a/docs/html/sitemap.json b/docs/html/sitemap.json deleted file mode 100644 index 38450dd..0000000 --- a/docs/html/sitemap.json +++ /dev/null @@ -1 +0,0 @@ -{"section":{"id":"","level":"0","number":null,"path":"index.html","title":"FISH-CONFIG"},"subsections":[{"section":{"id":"name","level":"1","number":"1","path":"1-name.html","title":"NAME"},"subsections":[]},{"section":{"id":"synopsis","level":"1","number":"2","path":"2-synopsis.html","title":"SYNOPSIS"},"subsections":[]},{"section":{"id":"description","level":"1","number":"3","path":"3-description.html","title":"DESCRIPTION"},"subsections":[]},{"section":{"id":"table-of-contents","level":"1","number":"4","path":"4-table-of-contents.html","title":"TABLE OF CONTENTS"},"subsections":[]},{"section":{"id":"1-configuration-variables","level":"1","number":"5","path":"5-1-configuration-variables.html","title":"1. CONFIGURATION VARIABLES"},"subsections":[{"section":{"id":"environment-directories-xdg","level":"2","number":"5.1","path":"5-1-configuration-variables.html#environment-directories-xdg","title":"Environment Directories (XDG)"},"subsections":[]},{"section":{"id":"tool-homes-xdg-compliant","level":"2","number":"5.2","path":"5-1-configuration-variables.html#tool-homes-xdg-compliant","title":"Tool Homes (XDG-compliant)"},"subsections":[]},{"section":{"id":"editor-and-pager","level":"2","number":"5.3","path":"5-1-configuration-variables.html#editor-and-pager","title":"Editor and Pager"},"subsections":[]},{"section":{"id":"scrollback-history","level":"2","number":"5.4","path":"5-1-configuration-variables.html#scrollback-history","title":"Scrollback History"},"subsections":[]},{"section":{"id":"other","level":"2","number":"5.5","path":"5-1-configuration-variables.html#other","title":"Other"},"subsections":[]},{"section":{"id":"pager-hierarchy","level":"2","number":"5.6","path":"5-1-configuration-variables.html#pager-hierarchy","title":"Pager Hierarchy"},"subsections":[]},{"section":{"id":"integrations","level":"2","number":"5.7","path":"5-1-configuration-variables.html#integrations","title":"Integrations"},"subsections":[{"section":{"id":"zoxide","level":"3","number":"5.7.1","path":"5-1-configuration-variables.html#zoxide","title":"Zoxide"},"subsections":[]},{"section":{"id":"direnv","level":"3","number":"5.7.2","path":"5-1-configuration-variables.html#direnv","title":"DirEnv"},"subsections":[]},{"section":{"id":"auto-python-venv","level":"3","number":"5.7.3","path":"5-1-configuration-variables.html#auto-python-venv","title":"Auto Python Venv"},"subsections":[]},{"section":{"id":"wakatime","level":"3","number":"5.7.4","path":"5-1-configuration-variables.html#wakatime","title":"WakaTime"},"subsections":[]},{"section":{"id":"tailscale","level":"3","number":"5.7.5","path":"5-1-configuration-variables.html#tailscale","title":"Tailscale"},"subsections":[]},{"section":{"id":"done-notifications","level":"3","number":"5.7.6","path":"5-1-configuration-variables.html#done-notifications","title":"Done Notifications"},"subsections":[]},{"section":{"id":"scrollback-history-1","level":"3","number":"5.7.7","path":"5-1-configuration-variables.html#scrollback-history-1","title":"Scrollback History"},"subsections":[]}]}]},{"section":{"id":"2-path-setup","level":"1","number":"6","path":"6-2-path-setup.html","title":"2. PATH SETUP"},"subsections":[]},{"section":{"id":"3-key-bindings","level":"1","number":"7","path":"7-3-key-bindings.html","title":"3. KEY BINDINGS"},"subsections":[{"section":{"id":"fzf-bindings-bundled-from-patrickf1fzffish","level":"2","number":"7.1","path":"7-3-key-bindings.html#fzf-bindings-bundled-from-patrickf1fzffish","title":"FZF Bindings (bundled from PatrickF1/fzf.fish)"},"subsections":[]}]},{"section":{"id":"4-abbreviations","level":"1","number":"8","path":"8-4-abbreviations.html","title":"4. ABBREVIATIONS"},"subsections":[{"section":{"id":"41-editors","level":"2","number":"8.1","path":"8-4-abbreviations.html#41-editors","title":"4.1 Editors"},"subsections":[]},{"section":{"id":"42-navigation-and-listing","level":"2","number":"8.2","path":"8-4-abbreviations.html#42-navigation-and-listing","title":"4.2 Navigation and Listing"},"subsections":[]},{"section":{"id":"43-git","level":"2","number":"8.3","path":"8-4-abbreviations.html#43-git","title":"4.3 Git"},"subsections":[]},{"section":{"id":"44-terminal-windows-tabs-and-panes","level":"2","number":"8.4","path":"8-4-abbreviations.html#44-terminal-windows-tabs-and-panes","title":"4.4 Terminal Windows, Tabs, and Panes"},"subsections":[]},{"section":{"id":"45-chezmoi","level":"2","number":"8.5","path":"8-4-abbreviations.html#45-chezmoi","title":"4.5 Chezmoi"},"subsections":[]},{"section":{"id":"46-docker","level":"2","number":"8.6","path":"8-4-abbreviations.html#46-docker","title":"4.6 Docker"},"subsections":[]},{"section":{"id":"47-systemctl","level":"2","number":"8.7","path":"8-4-abbreviations.html#47-systemctl","title":"4.7 Systemctl"},"subsections":[]},{"section":{"id":"48-ai-assistants","level":"2","number":"8.8","path":"8-4-abbreviations.html#48-ai-assistants","title":"4.8 AI Assistants"},"subsections":[]},{"section":{"id":"49-history-expansion","level":"2","number":"8.9","path":"8-4-abbreviations.html#49-history-expansion","title":"4.9 History Expansion"},"subsections":[]},{"section":{"id":"410-miscellaneous","level":"2","number":"8.10","path":"8-4-abbreviations.html#410-miscellaneous","title":"4.10 Miscellaneous"},"subsections":[]},{"section":{"id":"411-shell-aliases","level":"2","number":"8.11","path":"8-4-abbreviations.html#411-shell-aliases","title":"4.11 Shell Aliases"},"subsections":[{"section":{"id":"navigation","level":"3","number":"8.11.1","path":"8-4-abbreviations.html#navigation","title":"Navigation"},"subsections":[]},{"section":{"id":"color-overrides","level":"3","number":"8.11.2","path":"8-4-abbreviations.html#color-overrides","title":"Color Overrides"},"subsections":[]},{"section":{"id":"safety-wrappers","level":"3","number":"8.11.3","path":"8-4-abbreviations.html#safety-wrappers","title":"Safety Wrappers"},"subsections":[]},{"section":{"id":"archives-and-networking","level":"3","number":"8.11.4","path":"8-4-abbreviations.html#archives-and-networking","title":"Archives and Networking"},"subsections":[]},{"section":{"id":"system-logs","level":"3","number":"8.11.5","path":"8-4-abbreviations.html#system-logs","title":"System Logs"},"subsections":[]}]}]},{"section":{"id":"5-functions-reference","level":"1","number":"9","path":"9-5-functions-reference.html","title":"5. FUNCTIONS REFERENCE"},"subsections":[{"section":{"id":"51-file-and-directory","level":"2","number":"9.1","path":"9-5-functions-reference.html#51-file-and-directory","title":"5.1 File and Directory"},"subsections":[{"section":{"id":"cat","level":"3","number":"9.1.1","path":"9-5-functions-reference.html#cat","title":"cat"},"subsections":[]},{"section":{"id":"copy","level":"3","number":"9.1.2","path":"9-5-functions-reference.html#copy","title":"copy"},"subsections":[]},{"section":{"id":"du","level":"3","number":"9.1.3","path":"9-5-functions-reference.html#du","title":"du"},"subsections":[]},{"section":{"id":"dusize","level":"3","number":"9.1.4","path":"9-5-functions-reference.html#dusize","title":"dusize"},"subsections":[]},{"section":{"id":"ld","level":"3","number":"9.1.5","path":"9-5-functions-reference.html#ld","title":"lD"},"subsections":[]},{"section":{"id":"ls","level":"3","number":"9.1.6","path":"9-5-functions-reference.html#ls","title":"ls"},"subsections":[]},{"section":{"id":"lsr","level":"3","number":"9.1.7","path":"9-5-functions-reference.html#lsr","title":"lsr"},"subsections":[]},{"section":{"id":"lss","level":"3","number":"9.1.8","path":"9-5-functions-reference.html#lss","title":"lss"},"subsections":[]},{"section":{"id":"lstree","level":"3","number":"9.1.9","path":"9-5-functions-reference.html#lstree","title":"lstree"},"subsections":[]},{"section":{"id":"lt","level":"3","number":"9.1.10","path":"9-5-functions-reference.html#lt","title":"lt"},"subsections":[]},{"section":{"id":"ltr","level":"3","number":"9.1.11","path":"9-5-functions-reference.html#ltr","title":"ltr"},"subsections":[]},{"section":{"id":"lx","level":"3","number":"9.1.12","path":"9-5-functions-reference.html#lx","title":"lx"},"subsections":[]},{"section":{"id":"mkdir","level":"3","number":"9.1.13","path":"9-5-functions-reference.html#mkdir","title":"mkdir"},"subsections":[]},{"section":{"id":"mkcd","level":"3","number":"9.1.14","path":"9-5-functions-reference.html#mkcd","title":"mkcd"},"subsections":[]},{"section":{"id":"poke","level":"3","number":"9.1.15","path":"9-5-functions-reference.html#poke","title":"poke"},"subsections":[]},{"section":{"id":"rm","level":"3","number":"9.1.16","path":"9-5-functions-reference.html#rm","title":"rm"},"subsections":[]},{"section":{"id":"rg","level":"3","number":"9.1.17","path":"9-5-functions-reference.html#rg","title":"rg"},"subsections":[]},{"section":{"id":"scrub","level":"3","number":"9.1.18","path":"9-5-functions-reference.html#scrub","title":"scrub"},"subsections":[]}]},{"section":{"id":"52-navigation","level":"2","number":"9.2","path":"9-5-functions-reference.html#52-navigation","title":"5.2 Navigation"},"subsections":[{"section":{"id":"cdi","level":"3","number":"9.2.1","path":"9-5-functions-reference.html#cdi","title":"cdi"},"subsections":[]},{"section":{"id":"clone","level":"3","number":"9.2.2","path":"9-5-functions-reference.html#clone","title":"clone"},"subsections":[]},{"section":{"id":"clonet","level":"3","number":"9.2.3","path":"9-5-functions-reference.html#clonet","title":"clonet"},"subsections":[]}]},{"section":{"id":"53-editors-and-viewers","level":"2","number":"9.3","path":"9-5-functions-reference.html#53-editors-and-viewers","title":"5.3 Editors and Viewers"},"subsections":[{"section":{"id":"edit","level":"3","number":"9.3.1","path":"9-5-functions-reference.html#edit","title":"edit"},"subsections":[]},{"section":{"id":"fc","level":"3","number":"9.3.2","path":"9-5-functions-reference.html#fc","title":"fc"},"subsections":[]},{"section":{"id":"less","level":"3","number":"9.3.3","path":"9-5-functions-reference.html#less","title":"less"},"subsections":[]},{"section":{"id":"rawfish","level":"3","number":"9.3.4","path":"9-5-functions-reference.html#rawfish","title":"rawfish"},"subsections":[]},{"section":{"id":"view","level":"3","number":"9.3.5","path":"9-5-functions-reference.html#view","title":"view"},"subsections":[]}]},{"section":{"id":"54-git-and-version-control","level":"2","number":"9.4","path":"9-5-functions-reference.html#54-git-and-version-control","title":"5.4 Git and Version Control"},"subsections":[{"section":{"id":"auto-pull","level":"3","number":"9.4.1","path":"9-5-functions-reference.html#auto-pull","title":"auto-pull"},"subsections":[]},{"section":{"id":"branch","level":"3","number":"9.4.2","path":"9-5-functions-reference.html#branch","title":"branch"},"subsections":[]},{"section":{"id":"gi","level":"3","number":"9.4.3","path":"9-5-functions-reference.html#gi","title":"gi"},"subsections":[]},{"section":{"id":"git-clean","level":"3","number":"9.4.4","path":"9-5-functions-reference.html#git-clean","title":"git-clean"},"subsections":[]},{"section":{"id":"gitup","level":"3","number":"9.4.5","path":"9-5-functions-reference.html#gitup","title":"gitup"},"subsections":[]},{"section":{"id":"gitui","level":"3","number":"9.4.6","path":"9-5-functions-reference.html#gitui","title":"gitui"},"subsections":[]},{"section":{"id":"hist","level":"3","number":"9.4.7","path":"9-5-functions-reference.html#hist","title":"hist"},"subsections":[]}]},{"section":{"id":"55-package-management","level":"2","number":"9.5","path":"9-5-functions-reference.html#55-package-management","title":"5.5 Package Management"},"subsections":[{"section":{"id":"pkg","level":"3","number":"9.5.1","path":"9-5-functions-reference.html#pkg","title":"pkg"},"subsections":[]},{"section":{"id":"search","level":"3","number":"9.5.2","path":"9-5-functions-reference.html#search","title":"search"},"subsections":[]},{"section":{"id":"upgrade","level":"3","number":"9.5.3","path":"9-5-functions-reference.html#upgrade","title":"upgrade"},"subsections":[]},{"section":{"id":"cleanup","level":"3","number":"9.5.4","path":"9-5-functions-reference.html#cleanup","title":"cleanup"},"subsections":[]},{"section":{"id":"parur","level":"3","number":"9.5.5","path":"9-5-functions-reference.html#parur","title":"parur"},"subsections":[]}]},{"section":{"id":"56-dependency-management","level":"2","number":"9.6","path":"9-5-functions-reference.html#56-dependency-management","title":"5.6 Dependency Management"},"subsections":[{"section":{"id":"fish-deps","level":"3","number":"9.6.1","path":"9-5-functions-reference.html#fish-deps","title":"fish-deps"},"subsections":[]},{"section":{"id":"check_fish_deps","level":"3","number":"9.6.2","path":"9-5-functions-reference.html#check_fish_deps","title":"check_fish_deps"},"subsections":[]}]},{"section":{"id":"57-system-and-monitoring","level":"2","number":"9.7","path":"9-5-functions-reference.html#57-system-and-monitoring","title":"5.7 System and Monitoring"},"subsections":[{"section":{"id":"top","level":"3","number":"9.7.1","path":"9-5-functions-reference.html#top","title":"top"},"subsections":[]},{"section":{"id":"swapstat","level":"3","number":"9.7.2","path":"9-5-functions-reference.html#swapstat","title":"swapstat"},"subsections":[]},{"section":{"id":"sbver","level":"3","number":"9.7.3","path":"9-5-functions-reference.html#sbver","title":"sbver"},"subsections":[]},{"section":{"id":"ports","level":"3","number":"9.7.4","path":"9-5-functions-reference.html#ports","title":"ports"},"subsections":[]},{"section":{"id":"screensleep","level":"3","number":"9.7.5","path":"9-5-functions-reference.html#screensleep","title":"screensleep"},"subsections":[]},{"section":{"id":"lock","level":"3","number":"9.7.6","path":"9-5-functions-reference.html#lock","title":"lock"},"subsections":[]},{"section":{"id":"sudo-toggle","level":"3","number":"9.7.7","path":"9-5-functions-reference.html#sudo-toggle","title":"sudo-toggle"},"subsections":[]},{"section":{"id":"limine-edit","level":"3","number":"9.7.8","path":"9-5-functions-reference.html#limine-edit","title":"limine-edit"},"subsections":[]}]},{"section":{"id":"58-terminal-management","level":"2","number":"9.8","path":"9-5-functions-reference.html#58-terminal-management","title":"5.8 Terminal Management"},"subsections":[{"section":{"id":"tab","level":"3","number":"9.8.1","path":"9-5-functions-reference.html#tab","title":"tab"},"subsections":[]},{"section":{"id":"split","level":"3","number":"9.8.2","path":"9-5-functions-reference.html#split","title":"split"},"subsections":[]},{"section":{"id":"spwin","level":"3","number":"9.8.3","path":"9-5-functions-reference.html#spwin","title":"spwin"},"subsections":[]},{"section":{"id":"detach","level":"3","number":"9.8.4","path":"9-5-functions-reference.html#detach","title":"detach"},"subsections":[]},{"section":{"id":"bkg","level":"3","number":"9.8.5","path":"9-5-functions-reference.html#bkg","title":"bkg"},"subsections":[]},{"section":{"id":"ssh","level":"3","number":"9.8.6","path":"9-5-functions-reference.html#ssh","title":"ssh"},"subsections":[]}]},{"section":{"id":"59-clipboard","level":"2","number":"9.9","path":"9-5-functions-reference.html#59-clipboard","title":"5.9 Clipboard"},"subsections":[{"section":{"id":"y","level":"3","number":"9.9.1","path":"9-5-functions-reference.html#y","title":"y"},"subsections":[]},{"section":{"id":"p","level":"3","number":"9.9.2","path":"9-5-functions-reference.html#p","title":"p"},"subsections":[]},{"section":{"id":"paste","level":"3","number":"9.9.3","path":"9-5-functions-reference.html#paste","title":"paste"},"subsections":[]}]},{"section":{"id":"510-network","level":"2","number":"9.10","path":"9-5-functions-reference.html#510-network","title":"5.10 Network"},"subsections":[{"section":{"id":"gip","level":"3","number":"9.10.1","path":"9-5-functions-reference.html#gip","title":"gip"},"subsections":[]},{"section":{"id":"gip4","level":"3","number":"9.10.2","path":"9-5-functions-reference.html#gip4","title":"gip4"},"subsections":[]},{"section":{"id":"gip6","level":"3","number":"9.10.3","path":"9-5-functions-reference.html#gip6","title":"gip6"},"subsections":[]},{"section":{"id":"ping","level":"3","number":"9.10.4","path":"9-5-functions-reference.html#ping","title":"ping"},"subsections":[]},{"section":{"id":"qr","level":"3","number":"9.10.5","path":"9-5-functions-reference.html#qr","title":"qr"},"subsections":[]}]},{"section":{"id":"511-pager-and-logging","level":"2","number":"9.11","path":"9-5-functions-reference.html#511-pager-and-logging","title":"5.11 Pager and Logging"},"subsections":[{"section":{"id":"logs","level":"3","number":"9.11.1","path":"9-5-functions-reference.html#logs","title":"logs"},"subsections":[]},{"section":{"id":"smart_exit","level":"3","number":"9.11.2","path":"9-5-functions-reference.html#smart_exit","title":"smart_exit"},"subsections":[]}]},{"section":{"id":"512-ai-and-developer-tools","level":"2","number":"9.12","path":"9-5-functions-reference.html#512-ai-and-developer-tools","title":"5.12 AI and Developer Tools"},"subsections":[{"section":{"id":"agy","level":"3","number":"9.12.1","path":"9-5-functions-reference.html#agy","title":"agy"},"subsections":[]},{"section":{"id":"antigravity-ide","level":"3","number":"9.12.2","path":"9-5-functions-reference.html#antigravity-ide","title":"antigravity-ide"},"subsections":[]},{"section":{"id":"agents-init","level":"3","number":"9.12.3","path":"9-5-functions-reference.html#agents-init","title":"agents-init"},"subsections":[]},{"section":{"id":"claude","level":"3","number":"9.12.4","path":"9-5-functions-reference.html#claude","title":"claude"},"subsections":[]},{"section":{"id":"claude-docs","level":"3","number":"9.12.5","path":"9-5-functions-reference.html#claude-docs","title":"claude-docs"},"subsections":[]},{"section":{"id":"claude-pr","level":"3","number":"9.12.6","path":"9-5-functions-reference.html#claude-pr","title":"claude-pr"},"subsections":[]},{"section":{"id":"qc","level":"3","number":"9.12.7","path":"9-5-functions-reference.html#qc","title":"qc"},"subsections":[]},{"section":{"id":"superpowers","level":"3","number":"9.12.8","path":"9-5-functions-reference.html#superpowers","title":"superpowers"},"subsections":[]}]},{"section":{"id":"513-media-and-utilities","level":"2","number":"9.13","path":"9-5-functions-reference.html#513-media-and-utilities","title":"5.13 Media and Utilities"},"subsections":[{"section":{"id":"dng2avif","level":"3","number":"9.13.1","path":"9-5-functions-reference.html#dng2avif","title":"dng2avif"},"subsections":[]},{"section":{"id":"steam-dl","level":"3","number":"9.13.2","path":"9-5-functions-reference.html#steam-dl","title":"steam-dl"},"subsections":[]},{"section":{"id":"spark","level":"3","number":"9.13.3","path":"9-5-functions-reference.html#spark","title":"spark"},"subsections":[]},{"section":{"id":"yt-dlp","level":"3","number":"9.13.4","path":"9-5-functions-reference.html#yt-dlp","title":"yt-dlp"},"subsections":[]}]},{"section":{"id":"514-miscellaneous","level":"2","number":"9.14","path":"9-5-functions-reference.html#514-miscellaneous","title":"5.14 Miscellaneous"},"subsections":[{"section":{"id":"config-help","level":"3","number":"9.14.1","path":"9-5-functions-reference.html#config-help","title":"config-help"},"subsections":[]},{"section":{"id":"open-url","level":"3","number":"9.14.2","path":"9-5-functions-reference.html#open-url","title":"open-url"},"subsections":[]},{"section":{"id":"repo-open","level":"3","number":"9.14.3","path":"9-5-functions-reference.html#repo-open","title":"repo-open"},"subsections":[]},{"section":{"id":"config-update","level":"3","number":"9.14.4","path":"9-5-functions-reference.html#config-update","title":"config-update"},"subsections":[]},{"section":{"id":"config-settings","level":"3","number":"9.14.5","path":"9-5-functions-reference.html#config-settings","title":"config-settings"},"subsections":[]},{"section":{"id":"config-toggle-deprecated","level":"3","number":"9.14.6","path":"9-5-functions-reference.html#config-toggle-deprecated","title":"config-toggle (deprecated)"},"subsections":[]},{"section":{"id":"bash","level":"3","number":"9.14.7","path":"9-5-functions-reference.html#bash","title":"bash"},"subsections":[]},{"section":{"id":"bd-pull","level":"3","number":"9.14.8","path":"9-5-functions-reference.html#bd-pull","title":"bd-pull"},"subsections":[]},{"section":{"id":"cheat","level":"3","number":"9.14.9","path":"9-5-functions-reference.html#cheat","title":"cheat"},"subsections":[]},{"section":{"id":"cffetch--ffetch","level":"3","number":"9.14.10","path":"9-5-functions-reference.html#cffetch--ffetch","title":"cffetch / ffetch"},"subsections":[]},{"section":{"id":"dockup","level":"3","number":"9.14.11","path":"9-5-functions-reference.html#dockup","title":"dockup"},"subsections":[]},{"section":{"id":"joplin","level":"3","number":"9.14.12","path":"9-5-functions-reference.html#joplin","title":"joplin"},"subsections":[]},{"section":{"id":"ld-1","level":"3","number":"9.14.13","path":"9-5-functions-reference.html#ld-1","title":"ld"},"subsections":[]},{"section":{"id":"replay","level":"3","number":"9.14.14","path":"9-5-functions-reference.html#replay","title":"replay"},"subsections":[]},{"section":{"id":"kitty-logging","level":"3","number":"9.14.15","path":"9-5-functions-reference.html#kitty-logging","title":"kitty-logging"},"subsections":[]},{"section":{"id":"tmux-clean","level":"3","number":"9.14.16","path":"9-5-functions-reference.html#tmux-clean","title":"tmux-clean"},"subsections":[]},{"section":{"id":"wake-lock","level":"3","number":"9.14.17","path":"9-5-functions-reference.html#wake-lock","title":"wake-lock"},"subsections":[]}]}]},{"section":{"id":"6-dependency-catalog","level":"1","number":"10","path":"10-6-dependency-catalog.html","title":"6. DEPENDENCY CATALOG"},"subsections":[{"section":{"id":"required","level":"2","number":"10.1","path":"10-6-dependency-catalog.html#required","title":"Required"},"subsections":[]},{"section":{"id":"integrations-1","level":"2","number":"10.2","path":"10-6-dependency-catalog.html#integrations-1","title":"Integrations"},"subsections":[]},{"section":{"id":"recommended","level":"2","number":"10.3","path":"10-6-dependency-catalog.html#recommended","title":"Recommended"},"subsections":[]},{"section":{"id":"install-methods","level":"2","number":"10.4","path":"10-6-dependency-catalog.html#install-methods","title":"Install Methods"},"subsections":[]}]},{"section":{"id":"7-customization","level":"1","number":"11","path":"11-7-customization.html","title":"7. CUSTOMIZATION"},"subsections":[{"section":{"id":"machine-local-configuration","level":"2","number":"11.1","path":"11-7-customization.html#machine-local-configuration","title":"Machine-local Configuration"},"subsections":[]},{"section":{"id":"secrets-and-api-keys","level":"2","number":"11.2","path":"11-7-customization.html#secrets-and-api-keys","title":"Secrets and API Keys"},"subsections":[]},{"section":{"id":"overriding-configuration-variables","level":"2","number":"11.3","path":"11-7-customization.html#overriding-configuration-variables","title":"Overriding Configuration Variables"},"subsections":[]},{"section":{"id":"fish-universal-variables","level":"2","number":"11.4","path":"11-7-customization.html#fish-universal-variables","title":"Fish Universal Variables"},"subsections":[]},{"section":{"id":"opinionated-components-minimal-mode","level":"2","number":"11.5","path":"11-7-customization.html#opinionated-components-minimal-mode","title":"Opinionated Components (Minimal Mode)"},"subsections":[{"section":{"id":"component-reference","level":"3","number":"11.5.1","path":"11-7-customization.html#component-reference","title":"Component Reference"},"subsections":[{"section":{"id":"c1--command-shadows","level":"4","number":"11.5.1.1","path":"11-7-customization.html#c1--command-shadows","title":"C1 — Command Shadows"},"subsections":[]},{"section":{"id":"c2--startup-side-effects","level":"4","number":"11.5.1.2","path":"11-7-customization.html#c2--startup-side-effects","title":"C2 — Startup Side-Effects"},"subsections":[]},{"section":{"id":"c3--key-and-environment-overrides","level":"4","number":"11.5.1.3","path":"11-7-customization.html#c3--key-and-environment-overrides","title":"C3 — Key and Environment Overrides"},"subsections":[]},{"section":{"id":"c4--terminal-and-tool-integration","level":"4","number":"11.5.1.4","path":"11-7-customization.html#c4--terminal-and-tool-integration","title":"C4 — Terminal and Tool Integration"},"subsections":[]},{"section":{"id":"c5--logging-and-capture","level":"4","number":"11.5.1.5","path":"11-7-customization.html#c5--logging-and-capture","title":"C5 — Logging and Capture"},"subsections":[]},{"section":{"id":"c6--greeting-and-first-run-ui","level":"4","number":"11.5.1.6","path":"11-7-customization.html#c6--greeting-and-first-run-ui","title":"C6 — Greeting and First-Run UI"},"subsections":[]}]}]},{"section":{"id":"prompt-and-theme","level":"2","number":"11.6","path":"11-7-customization.html#prompt-and-theme","title":"Prompt and Theme"},"subsections":[{"section":{"id":"starship","level":"3","number":"11.6.1","path":"11-7-customization.html#starship","title":"Starship"},"subsections":[]},{"section":{"id":"catppuccin-fallback-prompt","level":"3","number":"11.6.2","path":"11-7-customization.html#catppuccin-fallback-prompt","title":"Catppuccin Fallback Prompt"},"subsections":[]},{"section":{"id":"fzf","level":"3","number":"11.6.3","path":"11-7-customization.html#fzf","title":"FZF"},"subsections":[]},{"section":{"id":"catppuccin-mocha-syntax-highlighting","level":"3","number":"11.6.4","path":"11-7-customization.html#catppuccin-mocha-syntax-highlighting","title":"Catppuccin Mocha Syntax Highlighting"},"subsections":[]}]}]},{"section":{"id":"8-fisher-plugins","level":"1","number":"12","path":"12-8-fisher-plugins.html","title":"8. FISHER PLUGINS"},"subsections":[{"section":{"id":"fisher-managed-plugins","level":"2","number":"12.1","path":"12-8-fisher-plugins.html#fisher-managed-plugins","title":"Fisher-Managed Plugins"},"subsections":[]},{"section":{"id":"sponge-history-filtering","level":"2","number":"12.2","path":"12-8-fisher-plugins.html#sponge-history-filtering","title":"Sponge History Filtering"},"subsections":[]},{"section":{"id":"bundled-plugin-functionality","level":"2","number":"12.3","path":"12-8-fisher-plugins.html#bundled-plugin-functionality","title":"Bundled Plugin Functionality"},"subsections":[]},{"section":{"id":"fish_plugins-manifest","level":"2","number":"12.4","path":"12-8-fisher-plugins.html#fish_plugins-manifest","title":"fish_plugins Manifest"},"subsections":[]}]},{"section":{"id":"9-installation","level":"1","number":"13","path":"13-9-installation.html","title":"9. INSTALLATION"},"subsections":[{"section":{"id":"return-sentinel","level":"2","number":"13.1","path":"13-9-installation.html#return-sentinel","title":"Return Sentinel"},"subsections":[]},{"section":{"id":"updating","level":"2","number":"13.2","path":"13-9-installation.html#updating","title":"Updating"},"subsections":[]}]},{"section":{"id":"10-personalization","level":"1","number":"14","path":"14-10-personalization.html","title":"10. PERSONALIZATION"},"subsections":[{"section":{"id":"secretsfish","level":"2","number":"14.1","path":"14-10-personalization.html#secretsfish","title":"secrets.fish"},"subsections":[]},{"section":{"id":"localfish","level":"2","number":"14.2","path":"14-10-personalization.html#localfish","title":"local.fish"},"subsections":[]}]},{"section":{"id":"11-viewing-this-manual","level":"1","number":"15","path":"15-11-viewing-this-manual.html","title":"11. VIEWING THIS MANUAL"},"subsections":[{"section":{"id":"with-ov-recommended","level":"2","number":"15.1","path":"15-11-viewing-this-manual.html#with-ov-recommended","title":"With ov (recommended)"},"subsections":[]},{"section":{"id":"with-bat","level":"2","number":"15.2","path":"15-11-viewing-this-manual.html#with-bat","title":"With bat"},"subsections":[]},{"section":{"id":"as-a-man-page","level":"2","number":"15.3","path":"15-11-viewing-this-manual.html#as-a-man-page","title":"As a man page"},"subsections":[]},{"section":{"id":"in-the-browser-html","level":"2","number":"15.4","path":"15-11-viewing-this-manual.html#in-the-browser-html","title":"In the browser (HTML)"},"subsections":[]},{"section":{"id":"as-a-wiki","level":"2","number":"15.5","path":"15-11-viewing-this-manual.html#as-a-wiki","title":"As a wiki"},"subsections":[]},{"section":{"id":"jumping-to-a-section","level":"2","number":"15.6","path":"15-11-viewing-this-manual.html#jumping-to-a-section","title":"Jumping to a section"},"subsections":[]}]}]} \ No newline at end of file diff --git a/docs/manual/05-functions/14-miscellaneous.md b/docs/manual/05-functions/14-miscellaneous.md index f7049db..bab9ee4 100644 --- a/docs/manual/05-functions/14-miscellaneous.md +++ b/docs/manual/05-functions/14-miscellaneous.md @@ -10,7 +10,7 @@ helpKeywords: ## config-help Synopsis: config-help [SECTION] - config-help [SECTION] --html + config-help --html config-help [SECTION] --man config-help -h | --help @@ -20,11 +20,11 @@ helpKeywords: keyword (case-insensitive; checks fish-config.index aliases first). Flags: - --html / -w Open docs/html/index.html in the default browser. - If SECTION is given, opens at the matching anchor. - Detects the browser via xdg-mime x-scheme-handler/https, - then known binaries, then xdg-open as last resort. - Respects $fish_help_browser and $BROWSER. + --html / -w Open the published documentation website + (https://fish-config-docs.pages.dev/) in the default + browser via xdg-open. Deep links to a section aren't + supported; if SECTION is given, a note points you to the + site's search box instead. --man / -m Open docs/fish-config.1 via man -l directly. If SECTION is given, jumps to the nearest match. --help / -h Print usage and navigation key reference. @@ -32,7 +32,6 @@ helpKeywords: config-help keybindings config-help pkg config-help --html - config-help pkg --html config-help --man config-help pkg --man @@ -60,7 +59,7 @@ helpKeywords: 5. xdg-open (last resort) open-url https://git.rootiest.dev/rootiest/fish-config - open-url "file://$HOME/.config/fish/docs/html/index.html" + open-url -v https://fish-config-docs.pages.dev/ Used internally by config-help --html. diff --git a/docs/manual/11-viewing-this-manual.md b/docs/manual/11-viewing-this-manual.md index 4e1079a..40848e3 100644 --- a/docs/manual/11-viewing-this-manual.md +++ b/docs/manual/11-viewing-this-manual.md @@ -8,25 +8,17 @@ helpKeywords: - manual --- -## With ov (recommended) +There are four ways to read this manual. - help config +## The documentation website -ov renders the Markdown with syntax highlighting and section-based -navigation. + help config --html - Space next section - ^ previous section - Alt+u toggle section list sidebar - / search forward - n / N next / previous search match - g go to line number - j interactive jump target (line, %, or 'section') - q quit - -## With bat - - bat --language=markdown --paging=always ~/.config/fish/docs/fish-config.md +Opens https://fish-config-docs.pages.dev/ in the default browser — the +Starlight-powered site built from `docs/manual/**` on every push to `main`. +It has a section sidebar and full-text search. Deep links to a specific +section aren't supported from the command line; once the site opens, use +its search box to jump straight to what you need. ## As a man page @@ -45,29 +37,36 @@ NOTE: fish-config (hyphen) is this config's man page. fish_config (underscore) is fish's built-in browser-based configuration tool — a completely separate command. Do not mix them up. -## In the browser (HTML) +## In the terminal - help config --html - help config pkg --html + help config + help config keybindings -Opens docs/html/index.html in the default web browser. If a section -keyword is given, the browser opens directly at the matching anchor -(resolved via docs/html/sitemap.json). Browser detection queries the -system's x-scheme-handler/https MIME entry (via xdg-mime) to find the -real browser binary, then falls back through known browser binaries -(firefox, chromium, vivaldi, etc.), and finally xdg-open as a last -resort. Set $fish_help_browser or $BROWSER to override. +Without a pager available beyond the basics, `help config [SECTION]` opens +the Markdown manual in the best available viewer, falling back through: -## As a wiki + 1. ov + bat section navigation + syntax highlighting (best) + 2. ov alone section navigation, raw Markdown + 3. bat alone syntax highlighting, use / to search + 4. man -l pre-compiled man page (if available) + 5. less plain text with line-jump + 6. cat plain output -The generated Markdown wiki lives in docs/wiki/. index.md provides the -project overview and a full table of contents. Each section page has a -navigation bar at the top linking to every other section. +With ov, the Markdown renders with syntax highlighting and section-based +navigation: -The wiki is auto-generated from this file by the CI pipeline on every -push to main that changes docs/fish-config.md. + Space next section + ^ previous section + Alt+u toggle section list sidebar + / search forward + n / N next / previous search match + g go to line number + j interactive jump target (line, %, or 'section') + q quit -## Jumping to a section +If SECTION is given, the pager opens at the first heading that matches the +keyword (case-insensitive; checks `docs/fish-config.index` aliases first, +then falls back to a normalized heading scan): help config keybindings help config abbreviations @@ -75,4 +74,12 @@ push to main that changes docs/fish-config.md. help config logs help config fish-deps -The keyword is matched case-insensitively against section headings. +## Reading the source directly + +`docs/manual/**` is the single source of truth this manual, the man page, +and the website are all generated from. Numbered files and directories +correspond to the numbered sections in this manual — browse them in any +editor, or from a shell: + + cd ~/.config/fish/docs/manual + grep -rn "keybindings" . diff --git a/docs/manualtools.py b/docs/manualtools.py index 9f76e59..685ed1e 100644 --- a/docs/manualtools.py +++ b/docs/manualtools.py @@ -4,7 +4,7 @@ """Shared helpers for the docs/manual SSOT pipeline. Frontmatter parsing, deterministic tree ordering, and heading level shifts. -Used by build-manual.py, split-manual.py, and verify-manual.py. +Used by build-manual.py and verify-manual.py. """ import re diff --git a/docs/split-manual.py b/docs/split-manual.py deleted file mode 100644 index 9188e4f..0000000 --- a/docs/split-manual.py +++ /dev/null @@ -1,207 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (C) 2026 Rootiest -# SPDX-License-Identifier: AGPL-3.0-or-later -"""One-shot migration: docs/fish-config.md -> docs/manual/**. - -Run once, verify with verify-manual.py, then delete this script. -""" - -import re -import shutil -import sys -from pathlib import Path - -import manualtools as mt - -DOCS = Path(__file__).parent -SRC = DOCS / "fish-config.md" -OUT = DOCS / "manual" -INDEX = DOCS / "fish-config.index" - -MAN_ONLY = {"NAME", "SYNOPSIS", "TABLE OF CONTENTS"} -LANDING = "DESCRIPTION" -FUNCTIONS_TITLE_RE = re.compile(r"^\d+\.\s+FUNCTIONS REFERENCE$", re.I) -NUM_PREFIX_RE = re.compile(r"^\d+(\.\d+)*\.?\s+") - - -def slugify(title: str) -> str: - s = NUM_PREFIX_RE.sub("", title).lower() - s = re.sub(r"[^\w\s-]", "", s) - return re.sub(r"[\s_]+", "-", s).strip("-") - - -def display_title(heading: str) -> str: - """Strip leading numbering and normalise SHOUTING to Title Case.""" - t = NUM_PREFIX_RE.sub("", heading).strip() - return t.title() if t.isupper() else t - - -def load_keywords() -> dict[str, list[str]]: - """Reverse fish-config.index into {heading text: [keywords]}.""" - mapping: dict[str, list[str]] = {} - if not INDEX.exists(): - return mapping - for line in INDEX.read_text().splitlines(): - line = line.strip() - if not line or line.startswith("#") or "=" not in line: - continue - keyword, heading = line.split("=", 1) - mapping.setdefault(heading.strip().lstrip("# ").strip(), []).append(keyword.strip()) - return mapping - - -def extract_raw_frontmatter(path: Path) -> str | None: - """Return the raw text between a file's opening `---` fences, or None. - - Unlike `mt.parse`, this does not round-trip the block through - `yaml.safe_load`/`yaml.safe_dump` — it hands back the exact original - bytes (minus the fence lines themselves) so a later verbatim re-emit - doesn't have to worry about quoting-style or scalar-coercion drift. - """ - text = path.read_text() - if not text.startswith("---\n"): - return None - end = text.find("\n---\n", 4) - if end == -1: - return None - return text[4:end] - - -def _trim_blank_lines(text: str) -> str: - """Drop leading/trailing blank lines without touching interior indentation. - - Plain `.strip()` also eats leading spaces on the first line, which - destroys 4-space-indented code blocks that start immediately after a - heading (e.g. the SYNOPSIS and TABLE OF CONTENTS sections). - """ - lines = text.split("\n") - while lines and lines[0].strip() == "": - lines.pop(0) - while lines and lines[-1].strip() == "": - lines.pop() - return "\n".join(lines) - - -def split_h1(text: str) -> list[tuple[str, str]]: - parts = re.split(r"^# (.+)$", text, flags=re.MULTILINE) - return [ - (parts[i].strip(), _trim_blank_lines(parts[i + 1])) for i in range(1, len(parts), 2) - ] - - -def split_h2(body: str) -> tuple[str, list[tuple[str, str]]]: - parts = re.split(r"^## (.+)$", body, flags=re.MULTILINE) - intro = _trim_blank_lines(parts[0]) - subs = [ - (parts[i].strip(), _trim_blank_lines(parts[i + 1])) for i in range(1, len(parts), 2) - ] - return intro, subs - - -def main() -> int: - if not SRC.exists(): - print(f"error: {SRC} not found", file=sys.stderr) - return 1 - if OUT.exists(): - shutil.rmtree(OUT) - OUT.mkdir(parents=True) - - keywords = load_keywords() - # SRC starts with a pandoc metadata block (title/section/header/date/ - # author) consumed by the man-page build. It has no purpose as an Astro - # page's frontmatter (index.md is also a website content page, and - # Starlight errors on any custom frontmatter key outside the fixed - # man/site/manTitle/helpKeywords schema), so it is extracted as raw text - # and written to docs/manual/_pandoc.yml instead of being folded into - # index.md's frontmatter. The leading underscore keeps Astro content - # collections from treating it as a page. build-manual.py --concat - # reads it back and re-emits it byte-for-byte. - pandoc_raw = extract_raw_frontmatter(SRC) - _, src_body = mt.parse(SRC) - sections = split_h1(src_body) - order = 0 - # `position` tracks each heading's place in the *original* document, - # including NAME/SYNOPSIS/DESCRIPTION/TABLE OF CONTENTS. It is what - # `sidebar.order` gets set to, so that manualtools.walk() (and thus - # build-manual.py --concat) reproduces the source order exactly. - # `order` (below) is unrelated: it only numbers the *numbered* sections - # (1. CONFIGURATION VARIABLES, 2. PATH SETUP, ...) for filenames. - position = 0 - - for heading, body in sections: - position += 1 - kw = keywords.get(heading, []) - if heading in MAN_ONLY: - path = OUT / f"00-{slugify(heading)}.md" - fm = { - "title": display_title(heading), - "manTitle": heading, - "man": True, - "site": False, - "sidebar": {"order": position}, - } - path.write_text(mt.serialize(fm, body)) - continue - - if heading == LANDING: - fm = { - "title": "Fish Shell Configuration", - "description": "Reference manual for the rootiest fish configuration.", - "manTitle": heading, - "sidebar": {"order": position}, - } - if kw: - fm["helpKeywords"] = kw - (OUT / "index.md").write_text(mt.serialize(fm, body)) - if pandoc_raw is not None: - (OUT / "_pandoc.yml").write_text(pandoc_raw.rstrip("\n") + "\n") - continue - - order += 1 - if FUNCTIONS_TITLE_RE.match(heading): - # Section 5 explodes into a directory of category files. - d = OUT / f"{order:02d}-functions" - d.mkdir() - intro, subs = split_h2(body) - fm = { - "title": display_title(heading), - "manTitle": heading, - "sidebar": {"order": position}, - } - if kw: - fm["helpKeywords"] = kw - (d / "index.md").write_text(mt.serialize(fm, intro)) - - for i, (sub_heading, sub_body) in enumerate(subs, start=1): - sub_fm = { - "title": display_title(sub_heading), - "manTitle": sub_heading, - "sidebar": {"order": i}, - } - sub_kw = keywords.get(sub_heading, []) - if sub_kw: - sub_fm["helpKeywords"] = sub_kw - # H3 function entries -> H2 so --site can split on them. - promoted = mt.shift_headings(sub_body, -1) - (d / f"{i:02d}-{slugify(sub_heading)}.md").write_text( - mt.serialize(sub_fm, promoted) - ) - continue - - fm = { - "title": display_title(heading), - "manTitle": heading, - "sidebar": {"order": position}, - } - if kw: - fm["helpKeywords"] = kw - (OUT / f"{order:02d}-{slugify(heading)}.md").write_text(mt.serialize(fm, body)) - - count = sum(1 for _ in OUT.rglob("*.md")) - print(f"wrote {count} files to {OUT}") - return 0 - - -if __name__ == "__main__": - sys.path.insert(0, str(Path(__file__).parent)) - raise SystemExit(main()) diff --git a/docs/split-wiki.py b/docs/split-wiki.py deleted file mode 100644 index 933466f..0000000 --- a/docs/split-wiki.py +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env python3 -"""Split docs/fish-config.md into a multi-page Markdown wiki in docs/wiki/. - -Index page: docs/wiki/index.md — DESCRIPTION intro + full ToC -Section pages: docs/wiki/-.md — one per numbered section, - with a top-level nav bar linking to every other section. -""" - -import re -import sys -from pathlib import Path - -# Sections whose content is merged into the index intro. -INTRO_TITLES = {"NAME", "SYNOPSIS", "DESCRIPTION"} - -# Sections that are skipped entirely (replaced by the generated ToC). -SKIP_TITLES = {"TABLE OF CONTENTS"} - - -def strip_front_matter(text: str) -> str: - """Remove pandoc YAML front matter (--- ... ---) from the start.""" - if text.startswith("---"): - end = text.index("\n---\n", 3) + 5 - return text[end:] - return text - - -def slugify(title: str) -> str: - """Convert a section title to a kebab-case filename slug.""" - s = title.lower() - s = re.sub(r"[^\w\s-]", "", s) - s = re.sub(r"[\s_]+", "-", s).strip("-") - return s - - -def build_nav(sections: list, current_filename: str | None = None) -> str: - """Return a one-line navigation bar for a section page.""" - parts = ["[Index](index.md)"] - for s in sections: - label = s["title"].title() - if s["filename"] == current_filename: - parts.append(f"**{label}**") - else: - parts.append(f"[{label}]({s['filename']})") - return "**Sections:** " + " | ".join(parts) - - -def build_full_toc(sections: list) -> str: - """Return a Markdown ToC list for the index page.""" - lines = ["## Table of Contents", ""] - for s in sections: - lines.append(f"- [{s['title'].title()}]({s['filename']})") - return "\n".join(lines) - - -def main() -> None: - src = Path("docs/fish-config.md") - out_dir = Path("docs/wiki") - - if not src.exists(): - print(f"error: {src} not found", file=sys.stderr) - sys.exit(1) - - out_dir.mkdir(parents=True, exist_ok=True) - - text = strip_front_matter(src.read_text()) - - # Split on level-1 headings; re.split keeps the delimiters. - parts = re.split(r"^(# .+)$", text, flags=re.MULTILINE) - # parts[0] — text before first heading (empty after front-matter strip) - # parts[1,3,…] — headings - # parts[2,4,…] — body content after each heading - - raw_sections = [] - for i in range(1, len(parts), 2): - heading = parts[i].strip() - body = parts[i + 1] if i + 1 < len(parts) else "" - title = heading[2:].strip() # strip leading '# ' - raw_sections.append({"heading": heading, "title": title, "body": body}) - - intro_parts = [] - numbered_sections = [] - for s in raw_sections: - if s["title"] in INTRO_TITLES: - if s["title"] == "DESCRIPTION": - intro_parts.append(s["body"].strip()) - elif s["title"] in SKIP_TITLES: - pass # discard; ToC is auto-generated - else: - slug = slugify(s["title"]) - s["filename"] = f"{slug}.md" - numbered_sections.append(s) - - # ── Write index.md ────────────────────────────────────────────────────── - intro_body = "\n\n".join(intro_parts).rstrip() - # Strip any trailing thematic break that the source adds before the ToC. - intro_body = re.sub(r"\n+---\s*$", "", intro_body) - toc = build_full_toc(numbered_sections) - index_content = f"# Fish Shell Configuration\n\n{intro_body}\n\n---\n\n{toc}\n" - (out_dir / "index.md").write_text(index_content) - print(" wrote docs/wiki/index.md") - - # ── Write section pages ────────────────────────────────────────────────── - for s in numbered_sections: - nav = build_nav(numbered_sections, current_filename=s["filename"]) - page_content = ( - f"{s['heading']}\n\n" - f"{nav}\n\n" - f"---\n\n" - f"{s['body'].strip()}\n" - ) - (out_dir / s["filename"]).write_text(page_content) - print(f" wrote docs/wiki/{s['filename']}") - - -if __name__ == "__main__": - main() diff --git a/docs/verify-manual.py b/docs/verify-manual.py index 8f0f391..caa63a1 100644 --- a/docs/verify-manual.py +++ b/docs/verify-manual.py @@ -11,7 +11,7 @@ from pathlib import Path import manualtools as mt # docs/build-manual.py follows this repo's hyphenated CLI-script naming -# convention (matching split-manual.py, verify-manual.py), which means it +# convention (matching verify-manual.py), which means it # cannot satisfy a plain `import build_manual` on its own — Python's import # statement never treats a hyphen as an underscore. Load it explicitly under # the name the tests expect and register it in sys.modules; every later diff --git a/docs/wiki/1-configuration-variables.md b/docs/wiki/1-configuration-variables.md deleted file mode 100644 index 873f5c9..0000000 --- a/docs/wiki/1-configuration-variables.md +++ /dev/null @@ -1,138 +0,0 @@ -# 1. CONFIGURATION VARIABLES - -**Sections:** [Index](index.md) | **1. Configuration Variables** | [2. Path Setup](2-path-setup.md) | [3. Key Bindings](3-key-bindings.md) | [4. Abbreviations](4-abbreviations.md) | [5. Functions Reference](5-functions-reference.md) | [6. Dependency Catalog](6-dependency-catalog.md) | [7. Customization](7-customization.md) | [8. Fisher Plugins](8-fisher-plugins.md) | [9. Installation](9-installation.md) | [10. Personalization](10-personalization.md) | [11. Viewing This Manual](11-viewing-this-manual.md) - ---- - -These variables are exported from config.fish on every interactive session. -Override them in local.fish (see Section 10, Personalization). - -## Environment Directories (XDG) - - XDG_CONFIG_HOME ~/.config - XDG_CACHE_HOME ~/.cache - XDG_DATA_HOME ~/.local/share - XDG_STATE_HOME ~/.local/state - -Tools that respect XDG are directed to these paths rather than polluting $HOME. - -## Tool Homes (XDG-compliant) - - CARGO_HOME $XDG_DATA_HOME/cargo - RUSTUP_HOME $XDG_DATA_HOME/rustup - GOPATH $XDG_DATA_HOME/go - BUN_INSTALL $XDG_DATA_HOME/bun - NPM_CONFIG_PREFIX $XDG_DATA_HOME/npm-global - GNUPGHOME $XDG_CONFIG_HOME/gnupg - WAKATIME_HOME $XDG_CONFIG_HOME/wakatime - -## Editor and Pager - - EDITOR nvim (falls back to vi if nvim is absent) - VISUAL unset by default; set a GUI editor via local.fish (the edit - function falls back to a GUI chain when VISUAL is empty) - SUDO_EDITOR same as EDITOR - PAGER ov (falls back to less) - -## Scrollback History - - __fish_scrollback_history_dir (unset → ~/.terminal_history) - __fish_scrollback_history_max_files (unset → 100) - SCROLLBACK_HISTORY_DIR ~/.terminal_history (exported mirror) - SCROLLBACK_HISTORY_MAX_FILES 100 (exported mirror) - -The __fish_scrollback_history_* universal variables are the fish-style source -of truth — set them via `config-settings` → Paths, or `set -U` directly. -config.fish exports the SCROLLBACK_HISTORY_* mirrors from them, because the -POSIX wrapper scripts (paru/yay/tmux/zellij logging and _prune_terminal_logs) -read the exported names from the environment. When the __fish_ vars are unset, -the documented defaults are exported. config.fish deliberately does not create -a global source var, which would shadow the universal and stop live edits from -taking effect. - -Scrollback logs accumulate in SCROLLBACK_HISTORY_DIR as timestamped files. -When the count exceeds SCROLLBACK_HISTORY_MAX_FILES the oldest are pruned -automatically on exit. Use `logs` to browse them interactively. - -## Other - - GPG_TTY $(tty) — ensures GPG passphrase prompts work - CLAUDE_CODE_NO_FLICKER 1 — suppress terminal flicker in Claude Code - CDPATH . ~/projects ~ - -Opinionated defaults (CDPATH, PAGER/MANPAGER, Vi mode, command shadows, -terminal integrations) can be switched off per category with universal -variables — see Section 7, "Opinionated Components (Minimal Mode)". - -## Pager Hierarchy - -$PAGER is set to ov when available, falling back to less. The less wrapper -function extends this into a full chain so anything that calls less directly -also benefits: - - $PAGER → ov → less → more → cat - -When bat is installed, man pages are rendered with syntax highlighting: - - MANROFFOPT -c - MANPAGER sh -c 'col -bx | bat -l man -p' - -## Integrations - -### Zoxide - -cd, z, and cdi/zi are all mapped to zoxide-backed navigation. Tab completions -for cd and z blend standard directory entries (CWD and CDPATH) with frecency -results so both familiar and frequently-visited paths appear in one list. - -### DirEnv - -Automatically loads .envrc files on directory change. Takes priority over -the auto-venv logic — if a directory is managed by direnv, the auto-venv -activation is skipped entirely. - -### Auto Python Venv - -When entering a directory that contains a .venv/, the virtualenv is activated -automatically and deactivated when you leave the project tree. - -### WakaTime - -Every shell command is reported to WakaTime for time-tracking. Set -FISH_WAKATIME_DISABLED=1 to disable without removing the plugin. - -### Tailscale - -Full tab completion for the tailscale CLI is provided via conf.d/tailscale.fish. - -### Done Notifications - -Desktop notifications fire when a command takes longer than 10 seconds and -the terminal window is not focused. Configured via fish universal variables: - - __done_min_cmd_duration 10000 ms - __done_notification_urgency_level low - -### Scrollback History - -When running inside Kitty, closing a shell session via exit saves a timestamped -scrollback snapshot to SCROLLBACK_HISTORY_DIR. Files are named: - - scrollback_YYYY-MM-DD_HH-MM-SS.log - -The paru and yay wrappers (auto-generated in ~/.local/bin/) run the command -inside a PTY via script(1) so download progress bars are preserved on screen, -then render the captured terminal animation down to a clean static log via -scripts/clean_progress_log.py (a small terminal-screen emulator that replays -cursor movements, collapses repainted progress frames to their final state, -and preserves ANSI color). If python3 is unavailable the wrapper falls back to -dropping only the script(1) header/footer. Output is saved to: - - paru_YYYY-MM-DD_HH-MM-SS.log - yay_YYYY-MM-DD_HH-MM-SS.log - -Before pruning, _scrollback_prune_junk silently removes empty files, files -with only a single meaningful line (e.g. bare [exited] captures), and Kitty -tab-rename prompt captures. Use exit --no-log (or exit -n) to skip capture. - ---- diff --git a/docs/wiki/10-personalization.md b/docs/wiki/10-personalization.md deleted file mode 100644 index 4553b76..0000000 --- a/docs/wiki/10-personalization.md +++ /dev/null @@ -1,64 +0,0 @@ -# 10. PERSONALIZATION - -**Sections:** [Index](index.md) | [1. Configuration Variables](1-configuration-variables.md) | [2. Path Setup](2-path-setup.md) | [3. Key Bindings](3-key-bindings.md) | [4. Abbreviations](4-abbreviations.md) | [5. Functions Reference](5-functions-reference.md) | [6. Dependency Catalog](6-dependency-catalog.md) | [7. Customization](7-customization.md) | [8. Fisher Plugins](8-fisher-plugins.md) | [9. Installation](9-installation.md) | **10. Personalization** | [11. Viewing This Manual](11-viewing-this-manual.md) - ---- - -Sensitive credentials and machine-specific settings are kept out of version -control in a private directory. The path defaults to -`~/.config/.user-dots/fish/` but can be overridden: - - set -U __fish_user_dots_path /path/to/your/dots/fish - -Or use the interactive TUI — run `config-settings` and navigate to the -"Dots Path" row (last row). Press Enter to type a new path, or ← / h to -reset to the default. - -config.fish sources local.fish from that directory on every interactive -session. local.fish is responsible for sourcing its own secrets.fish: - - $__fish_user_dots_path/ - ├── secrets.fish API keys, tokens, passwords, personal identifiers - └── local.fish Machine-specific paths, env vars, and sourcing secrets - -fish_variables (auto-managed by fish) is excluded from this repo via -.gitignore. Do not commit it. - -## secrets.fish - -Store anything you would not commit to a public repo: API keys, auth tokens, -passwords, and personal identifiers. - - set -gx MY_NAME "Your Name" - set -gx MY_EMAIL "you@example.com" - set -gx GPG_RECIPIENT "you@example.com" - set -gx GITHUB_TOKEN ghp_yourTokenHere - set -gx OPENAI_API_KEY sk-proj-yourKeyHere - set -gx GITEA_TOKEN yourGiteaTokenHere - set -gx GITEA_CHOSEN_LOGIN your.gitea.instance - set -gx KOPIA_PASSWORD yourKopiaPassword - -## local.fish - -Store paths and variables specific to one machine — things that would be -wrong on any other system. - - # CDPATH — directories searched by cd - set -gx CDPATH . /home/youruser/projects /home/youruser - - # Path to your shared .gitignore boilerplate - set -gx GITIGNORE_BOILERPLATE ~/.config/git/gitignore_boilerplate - - # SSH shortcuts - abbr -a sshr 'ssh you@your-server.local' - abbr -a sshw 'ssh you@work-server.example.com' - - # Docker context shortcuts - abbr -a dcr 'docker context use my-remote-server' - abbr -a dcw 'docker context use work-server' - -local.fish is sourced at the end of config.fish with an existence check so -the public config works cleanly on any machine without the private repo. -local.fish in turn sources secrets.fish when it exists. - ---- diff --git a/docs/wiki/11-viewing-this-manual.md b/docs/wiki/11-viewing-this-manual.md deleted file mode 100644 index 5b3330c..0000000 --- a/docs/wiki/11-viewing-this-manual.md +++ /dev/null @@ -1,74 +0,0 @@ -# 11. VIEWING THIS MANUAL - -**Sections:** [Index](index.md) | [1. Configuration Variables](1-configuration-variables.md) | [2. Path Setup](2-path-setup.md) | [3. Key Bindings](3-key-bindings.md) | [4. Abbreviations](4-abbreviations.md) | [5. Functions Reference](5-functions-reference.md) | [6. Dependency Catalog](6-dependency-catalog.md) | [7. Customization](7-customization.md) | [8. Fisher Plugins](8-fisher-plugins.md) | [9. Installation](9-installation.md) | [10. Personalization](10-personalization.md) | **11. Viewing This Manual** - ---- - -## With ov (recommended) - - help config - -ov renders the Markdown with syntax highlighting and section-based -navigation. - - Space next section - ^ previous section - Alt+u toggle section list sidebar - / search forward - n / N next / previous search match - g go to line number - j interactive jump target (line, %, or 'section') - q quit - -## With bat - - bat --language=markdown --paging=always ~/.config/fish/docs/fish-config.md - -## As a man page - - help config --man - help config pkg --man - -Opens the compiled docs/fish-config.1 directly via man -l, bypassing -the pager fallback chain. If a section keyword is given, the pager opens -at the nearest matching heading. The symlink is created once on first -run (like an install step) and MANPATH is set each session, enabling -the standard invocation: - - man fish-config - -NOTE: fish-config (hyphen) is this config's man page. fish_config -(underscore) is fish's built-in browser-based configuration tool — -a completely separate command. Do not mix them up. - -## In the browser (HTML) - - help config --html - help config pkg --html - -Opens docs/html/index.html in the default web browser. If a section -keyword is given, the browser opens directly at the matching anchor -(resolved via docs/html/sitemap.json). Browser detection queries the -system's x-scheme-handler/https MIME entry (via xdg-mime) to find the -real browser binary, then falls back through known browser binaries -(firefox, chromium, vivaldi, etc.), and finally xdg-open as a last -resort. Set $fish_help_browser or $BROWSER to override. - -## As a wiki - -The generated Markdown wiki lives in docs/wiki/. index.md provides the -project overview and a full table of contents. Each section page has a -navigation bar at the top linking to every other section. - -The wiki is auto-generated from this file by the CI pipeline on every -push to main that changes docs/fish-config.md. - -## Jumping to a section - - help config keybindings - help config abbreviations - help config pkg - help config logs - help config fish-deps - -The keyword is matched case-insensitively against section headings. diff --git a/docs/wiki/2-path-setup.md b/docs/wiki/2-path-setup.md deleted file mode 100644 index a1c1c7d..0000000 --- a/docs/wiki/2-path-setup.md +++ /dev/null @@ -1,22 +0,0 @@ -# 2. PATH SETUP - -**Sections:** [Index](index.md) | [1. Configuration Variables](1-configuration-variables.md) | **2. Path Setup** | [3. Key Bindings](3-key-bindings.md) | [4. Abbreviations](4-abbreviations.md) | [5. Functions Reference](5-functions-reference.md) | [6. Dependency Catalog](6-dependency-catalog.md) | [7. Customization](7-customization.md) | [8. Fisher Plugins](8-fisher-plugins.md) | [9. Installation](9-installation.md) | [10. Personalization](10-personalization.md) | [11. Viewing This Manual](11-viewing-this-manual.md) - ---- - -Directories prepended to PATH in this order (first wins): - - ~/.local/bin Standard user-local executables - ~/Applications User-installed standalone apps - ~/scripts Personal shell scripts - ~/bin Cargo binaries (appended — lowest priority) - $BUN_INSTALL/bin Bun runtime and global packages - $NPM_CONFIG_PREFIX/bin Global npm packages - ~/.lmstudio/bin LM Studio CLI - ~/.resend/bin Resend CLI - ~/.fzf/bin fzf binary (git-installed) - -Cargo binaries are intentionally appended (lowest priority) to avoid -shadowing system-installed Rust tools. - ---- diff --git a/docs/wiki/3-key-bindings.md b/docs/wiki/3-key-bindings.md deleted file mode 100644 index 4319d2f..0000000 --- a/docs/wiki/3-key-bindings.md +++ /dev/null @@ -1,52 +0,0 @@ -# 3. KEY BINDINGS - -**Sections:** [Index](index.md) | [1. Configuration Variables](1-configuration-variables.md) | [2. Path Setup](2-path-setup.md) | **3. Key Bindings** | [4. Abbreviations](4-abbreviations.md) | [5. Functions Reference](5-functions-reference.md) | [6. Dependency Catalog](6-dependency-catalog.md) | [7. Customization](7-customization.md) | [8. Fisher Plugins](8-fisher-plugins.md) | [9. Installation](9-installation.md) | [10. Personalization](10-personalization.md) | [11. Viewing This Manual](11-viewing-this-manual.md) - ---- - -The shell uses Vi key bindings (fish_vi_key_bindings). All custom bindings -are active in Insert, Normal, and Visual modes unless noted. - - Binding Action - ───────────────────────────────────────────────────────────────────── - Ctrl+G Insert the head of the previous command's last path - argument. Equivalent to !$:h in Bash. - Example: previous = "cd /usr/local/bin" - Ctrl+G inserts "/usr/local" - - Ctrl+F Interactive history substitution. Type old/new then - press Ctrl+F to apply s/old/new/ to the previous - command. Equivalent to !!:s/old/new/ in Bash. - Example: previous = "echo this is a test" - type "this is/that was", press Ctrl+F - result = "echo that was a test" - - Ctrl+Alt+U Strip the first token of the current command line, - leaving arguments in place with the cursor at the - start. Useful for quickly retyping the command. - Example: "mkdir new_folder" -> " new_folder" - - Ctrl+Alt+= Evaluate the current command line buffer with - Qalculate! (qalc) and print the result inline. - Requires qalc to be installed. - Example: type "150 * 1.08", press Ctrl+Alt+= - prints 162 - - Ctrl+Enter Smart execute: runs commands instantly without - pressing Enter a second time for certain fast-path - commands (speedtest-fast, etc.). - - @@ FZF inline picker. Type @@ anywhere on the command - line to open an fzf picker and insert a selection - at the cursor position. - -## FZF Bindings (bundled from PatrickF1/fzf.fish) - - Ctrl+R Search command history - Ctrl+Alt+F Search git-tracked files - Ctrl+Alt+L Search git log - Ctrl+Alt+S Search git status - Ctrl+V Search shell variables - Ctrl+Alt+P Search running processes - ---- diff --git a/docs/wiki/4-abbreviations.md b/docs/wiki/4-abbreviations.md deleted file mode 100644 index 2c7937f..0000000 --- a/docs/wiki/4-abbreviations.md +++ /dev/null @@ -1,188 +0,0 @@ -# 4. ABBREVIATIONS - -**Sections:** [Index](index.md) | [1. Configuration Variables](1-configuration-variables.md) | [2. Path Setup](2-path-setup.md) | [3. Key Bindings](3-key-bindings.md) | **4. Abbreviations** | [5. Functions Reference](5-functions-reference.md) | [6. Dependency Catalog](6-dependency-catalog.md) | [7. Customization](7-customization.md) | [8. Fisher Plugins](8-fisher-plugins.md) | [9. Installation](9-installation.md) | [10. Personalization](10-personalization.md) | [11. Viewing This Manual](11-viewing-this-manual.md) - ---- - -Abbreviations expand when you press Space or Enter. They are terminal-aware: -some expand differently in Kitty vs WezTerm vs other terminals. - -## 4.1 Editors - - n / nv / neovim nvim - e edit - se sudoedit - k kate - editt Open new tab with nvim (terminal-aware) - cdnv cd ~/.config/nvim - cdnvn cd ~/.config/nvim; nvim - -## 4.2 Navigation and Listing - - l ls - lS lss (sort by size) - lsR lsr (sort by time, oldest first) - lX lx (sort by extension) - lT lt (tree, depth 2) - lsT lstree (full recursive tree) - lzd ld (lazydocker) - cdi zi (interactive zoxide picker) - -## 4.3 Git - - g git - lg lazygit - gitig / git-ignore gi (generate .gitignore) - -## 4.4 Terminal Windows, Tabs, and Panes - -These abbreviations control the terminal emulator. Each has a Kitty -variant and a WezTerm variant; the correct one is inserted based on -$TERM or $TERM_PROGRAM. - - :w New OS window - :wv Split pane horizontally (new pane below) - :wh Split pane vertically (new pane to the right) - :wo Detach current window to its own OS window - :wot Move current pane to a new tab - :t New tab - :tl Set tab title - :tw Set window title - :twk Rename workspace (WezTerm only) - :tp Focus previous tab - :tn Focus next tab - :q Close current pane/window - :Q Close current tab - :sw spwin (spawn new OS window) - -Quick-navigate shortcuts open windows/tabs/panes with preset working dirs: - - :tgk New tab at ~/.config/kitty - :tgn New tab at ~/.config/nvim - :tgf New tab at ~/.config/fish - :tgh New tab at ~ - :tgcz New tab at chezmoi source dir - :tgcm New tab at chezmoi source dir - :tgp New tab at ~/projects - :tgr New tab at / (root) - -Prefixes :wg* and :wvg* / :whg* open OS windows or splits to the same -set of dirs, respectively. - -Prefixes :cd* open tabs with a quick cd shortcut: - - :cdn cd ~/.config/nvim - :cdf cd ~/.config/fish - :cdh cd ~ - :cdcz cd to chezmoi source - :cdp cd ~/projects - -Appending n to any :cd* abbreviation also runs nvim after changing dir. - -## 4.5 Chezmoi - - cm / cme / cmi / cmap / cmad / cmrm / cmcd / - cz / cze / czi / czap / czad / czrm / czcd - - cm / cz chezmoi - cmcd / czcd chezmoi cd - cme / cze chezmoi edit - cmad / czad chezmoi add - cmap / czap chezmoi apply - cmrm / cmf / czrm / czf chezmoi forget - cmi / czi chezmoi init - -## 4.6 Docker - - dcl docker context use default - dcls docker context ls - lzd ld (lazydocker) - -## 4.7 Systemctl - - sc systemctl - ssc sudo systemctl - scu systemctl --user - st systemctl status - scs sudo systemctl start - scr sudo systemctl restart - ssct sudo systemctl start - sscs sudo systemctl stop - sscr sudo systemctl restart - -## 4.8 AI Assistants - - ag agy - ag. agy . - v antigravity-ide - s wezterm ssh (WezTerm only) - -## 4.9 History Expansion - -These are implemented as keybinding helpers, but can also be typed: - - !^ Expand to first argument of previous command - !* Expand to all arguments of previous command - typo_sub Interactive typo substitution (Ctrl+F) - bang_string !string expansion - bang_search !?string search - bang_minus_n !-n (nth-previous command) - -## 4.10 Miscellaneous - - /exit exit - :q Close pane (alias for terminal close) - :Q Close tab - sudu sudo -s - kt kitty (Kitty only) - c cat - speedtest-fast fast-cli - bl bd list - bs bd sync - bC bd create --title - bsh bd show - lb lazybeads - -## 4.11 Shell Aliases - -These aliases are defined in conf.d/tricks.fish via alias (which creates Fish -functions). They are active in all interactive sessions. - -### Navigation - - .. cd .. - ... cd ../.. - .... cd ../../.. - ..... cd ../../../.. - ...... cd ../../../../.. - -### Color Overrides - -Force color output for common tools: - - grep grep --color=auto - fgrep fgrep --color=auto - egrep egrep --color=auto - dir dir --color=auto - vdir vdir --color=auto - -### Safety Wrappers - -Add -i (interactive confirmation) to destructive commands: - - cp cp -i - mv mv -i - -### Archives and Networking - - tarnow tar -acf Create compressed archive (auto-detects format) - untar tar -zxvf Extract a gzip-compressed archive - wget wget -c Resume interrupted downloads by default - tb nc termbin.com 9999 Pipe content to termbin.com for quick sharing - -### System Logs - - jctl journalctl -p 3 -xb Show priority-3 (error) journal entries - from the current boot - ---- diff --git a/docs/wiki/5-functions-reference.md b/docs/wiki/5-functions-reference.md deleted file mode 100644 index c72b16a..0000000 --- a/docs/wiki/5-functions-reference.md +++ /dev/null @@ -1,1086 +0,0 @@ -# 5. FUNCTIONS REFERENCE - -**Sections:** [Index](index.md) | [1. Configuration Variables](1-configuration-variables.md) | [2. Path Setup](2-path-setup.md) | [3. Key Bindings](3-key-bindings.md) | [4. Abbreviations](4-abbreviations.md) | **5. Functions Reference** | [6. Dependency Catalog](6-dependency-catalog.md) | [7. Customization](7-customization.md) | [8. Fisher Plugins](8-fisher-plugins.md) | [9. Installation](9-installation.md) | [10. Personalization](10-personalization.md) | [11. Viewing This Manual](11-viewing-this-manual.md) - ---- - -## 5.1 File and Directory - -### cat - - Synopsis: cat [args...] - Wraps bat for files with syntax highlighting and line numbers. - Passes directories to ls. Falls back to /usr/bin/cat. - - cat README.md - cat ~/projects/myapp - -### copy - - Synopsis: copy - Wraps cp, stripping trailing slashes from source directories to - prevent unintended nesting inside the destination. - - copy ./mydir/ ~/backup # copies mydir INTO backup, not backup/mydir/ - -### du - - Synopsis: du [--disk|--dir|--dua] [args...] - Smart disk-usage dispatcher: - --disk force duf (disk-level free/used overview) - --dir force dust (per-directory tree breakdown) - --dua force dua (fast space analyzer) - Without flags, routes to the most appropriate tool by context. - - du ~/Downloads - du --disk - -### dusize - - Synopsis: dusize [dir] - Human-readable disk usage for a directory via du -sh. Defaults to cwd. - - dusize ~/Videos - -### lD - - Synopsis: lD [args...] - Lists directories only in long format with icons. Uses eza, falls back - to lsd, then system ls. - - lD ~/projects - -### ls - - Synopsis: ls [args...] - Lists files in long format with icons and hyperlinks. Uses eza, falls - back to lsd, then system ls. - - ls - ls -a ~/projects - -### lsr - - Synopsis: lsr [args...] - Lists files sorted by modification time, oldest first. Uses eza. - -### lss - - Synopsis: lss [args...] - Lists files sorted by size with gradient color scaling. Uses eza. - -### lstree - - Synopsis: lstree [args...] - Full recursive tree view with icons. Uses eza. - - lstree ~/projects/myapp - -### lt - - Synopsis: lt [args...] - Tree view limited to depth 2 with icons. Uses eza. - - lt ~/projects - -### ltr - - Synopsis: ltr [args...] - Lists files sorted by modification time, oldest first, long format with - age-based gradient scaling. Uses eza. - -### lx - - Synopsis: lx [args...] - Lists files sorted by extension, long format. Uses eza. - -### mkdir - - Synopsis: mkdir [args...] - Interactive mkdir that prints a tree of created directories. - Falls back to mkdir -p silently. - - mkdir ~/projects/myapp/src - -### mkcd - - Synopsis: mkcd [-s] - Creates a directory (including parents) and cd into it. Prints a tree - of created dirs by default; -s/--silent suppresses output. - - mkcd ~/projects/newapp/src - -### poke - - Synopsis: poke [file...] - Creates files via touch, automatically creating any missing parent - directories first. - - poke ~/projects/new/src/main.fish - -### rm - - Synopsis: rm [-e [opts] | -S | args...] - Safe rm wrapper routing to trash: - - (no args) List current trash contents - -e/--empty Empty the trash (pass options to trash-empty) - -S/--secure Permanently delete via rm -rf + fstrim (irreversible) - -r/-R/--recursive Move to trash - Move to trash (safe delete) - - Falls back to /usr/bin/rm when trash is unavailable. - - rm file.txt # moves to trash - rm -e # empty trash - rm -S sensitive.pem # permanent delete - -### rg - - Synopsis: rg [args...] - In Kitty, wraps ripgrep with --hyperlink-format=kitty so search - results are clickable file links in the terminal. Falls back to - system rg in any other terminal. All other arguments pass through - unchanged. - - rg "fish_greeting" ~/.config/fish/ - rg -l "TODO" ~/projects/myapp - -### scrub - - Synopsis: scrub [-a] [-d] [-h] - Recursively removes OS metadata, editor artifacts, compiler output, - and dev caches using fd. - - -a/--aggressive Also removes node_modules, logs, .cache, IDE dirs, - AI session artifacts - -d/--dry-run Print what would be removed without deleting - - scrub - scrub -a - scrub -d - ---- - -## 5.2 Navigation - -### cdi - - Synopsis: cdi [query] - Interactive directory picker combining zoxide frecency with fzf. - Equivalent to zi. - - cdi myproject - -### clone - - Synopsis: clone [args...] - Clone a git repository into a new Kitty window. Kitty-only. - - clone https://github.com/user/repo.git - -### clonet - - Synopsis: clonet [args...] - Clone a git repository into a new Kitty tab. Kitty-only. - - clonet https://github.com/user/repo.git - ---- - -## 5.3 Editors and Viewers - -### edit - - Synopsis: edit [-V|-t] [-e EDITOR] [-c] [-x TEXT] [-n] [-v|-s] [FILE...] - - Opens files in a text editor, choosing a terminal or GUI editor and - resolving a rich chain of fallbacks. With no --visual/--terminal flag the - mode is auto-detected: interactive terminals use the terminal editor - ($EDITOR), while detached invocations (e.g. desktop shortcuts) use the GUI - editor ($VISUAL). Clipboard contents and literal strings can be opened as - throwaway temp files. Editor output is suppressed unless --verbose. - - GUI fallback chain: zed → antigravity-ide → code → kate → kwrite → - gnome-text-editor → gedit - Terminal fallback chain: nvim → vim → micro → nano → vi - - Options: - -V, --visual Force the GUI editor ($VISUAL or fallbacks) - -t, --terminal Force the terminal editor ($EDITOR or fallbacks) - -e, --editor=X Use a specific editor binary X - -c, --clipboard Open the clipboard contents (as a temp file) - -x, --text=STR Open STR as the contents of a new temp file - -n, --new Force a new window/instance (best-effort) - -v, --verbose Print the launch command and editor output - -s, --silent Suppress all output, including the editor's - -h, --help Show this help message - - edit ~/.config/fish/config.fish - edit --visual notes.txt - edit --terminal --new todo.md - edit --editor=code --clipboard - edit --text="hello world" - -### fc - - Synopsis: fc [command_prefix] - Edit the last shell command (or one matching a prefix) in $EDITOR, - then execute the result. Bash-style fc behaviour. - - fc - fc git - -### less - - Synopsis: less [args...] - Pager wrapper with fallback chain: $PAGER -> ov -> less -> more -> cat. - - less /var/log/syslog - -### rawfish - - Synopsis: rawfish [args...] - Launches Fish with NO_TMUX=1, bypassing any tmux auto-attach logic. - Useful when you need a clean shell without session management. - -### view - - Synopsis: view [args...] - Opens files in nvim read-only mode (-R). Falls back to less. - - view /etc/fstab - ---- - -## 5.4 Git and Version Control - -### auto-pull - - Synopsis: auto-pull [list] - auto-pull add [PATH] - auto-pull remove - auto-pull status - - Manages the registry of repositories that are background fast-forwarded - when you enter them (see "Auto-pull fast-forward" under the C2 component - reference). The fish-config repo is always covered as a baseline. The - registry is machine-local at `$__fish_user_dots_path/auto-pull.list` (defaults - to `~/.config/.user-dots/fish/auto-pull.list`), one absolute path per line, - and is never committed. Registry management works - even when C2 auto-execution is disabled; only the background sync is gated. - - list Show registered repos (default) - add [PATH] Register PATH's git root (default: current repo) - remove Unregister by basename or exact path - status Show enabled/disabled state, repo count, list path - - cd ~/src/qmk_firmware; and auto-pull add - auto-pull add ~/work/api - auto-pull list - auto-pull remove qmk_firmware - -### branch - - Synopsis: branch - Switches to a local branch, or creates it if it does not exist. - - branch feature/new-ui - -### gi - - Synopsis: gi [-h] [-b] [-p] [-s] [-l] [targets...] - Generates .gitignore content from the gitignore.io API with MD5-based - deduplication (patterns already present are not re-appended). - - -b/--boilerplate Append generic boilerplate first - -p/--prompt Prompt interactively for targets - -s/--stdout Print to stdout instead of appending to .gitignore - -l/--list List all available targets - targets Comma-separated or space-separated target names - - gi python,venv - gi -b -p - gi -s node > .gitignore - -### git-clean - - Synopsis: git-clean [-f] - Fetches and prunes the remote, fast-forwards the current branch, then - deletes local branches whose remote tracking branch has been deleted. - Switches to main/master automatically if the current branch is orphaned. - - -f/--force Force-delete unmerged branches too - - git-clean - git-clean --force - -### gitup - - Synopsis: gitup [args...] - Fetches updates from the remote and shows git status. Extra args are - forwarded to git fetch. - - gitup - gitup --all - -### gitui - - Synopsis: gitui [args...] - Launches gitui with the Catppuccin Frappe theme pre-applied. - -### hist - - Synopsis: hist - Searches shell history with fzf, inserts the selection into the command - line, and copies it to the clipboard via wl-copy. - ---- - -## 5.5 Package Management - -### pkg - - Synopsis: pkg [-h] [-i|-u] [package...] - Installs or removes packages using the detected system package manager. - Supports: paru, yay, pacman, apt, dnf, zypper, yum, brew, pkg. - - (no flag) Auto mode: installs missing packages, removes installed ones - -i/--install Force install - -u/--uninstall Force uninstall - - pkg firefox # auto: install if missing, remove if present - pkg -i ripgrep fd # force install - pkg -u cowsay # force uninstall - - The package-installed check uses the correct query for each PM: - pacman/paru/yay pacman -Qi - apt dpkg -s - dnf/zypper/yum rpm -q - brew brew list - pkg pkg info - -### search - - Synopsis: search [args...] - Interactive AUR package search and install via paru or yay. - Arch Linux only. - - search neovim - -### upgrade - - Synopsis: upgrade - Full system upgrade via paru -Syu --noconfirm or yay -Syu --noconfirm. - Arch Linux only. - -### cleanup - - Synopsis: cleanup - Lists and removes orphan packages via pacman, logging their names to - ~/.removed_orphans. Arch Linux only. - -### parur - - Synopsis: parur - Opens an fzf picker of all installed packages (with pacman -Qi previews), - then removes the selected packages via paru or yay. Arch Linux only. - - parur - ---- - -## 5.6 Dependency Management - -### fish-deps - - Synopsis: fish-deps [status|install|update|sync] - Unified command for managing all tools this configuration depends on. - - status (default) Show installed/missing status grouped by tier - install Interactively install each missing dependency - update Update all installed dependencies - sync Install missing deps, then update all - - Install method priority (highest to lowest): - 1. git+cargo source build (fish shell itself) - 2. cargo (Rust tools — gets latest crate version) - 3. system PM (paru/apt/brew/etc.) - 4. git clone (fzf) - 5. curl installer (starship, fisher, uv) - - When multiple methods are available you are prompted to choose. - - Dependencies are grouped into three tiers: - - Required fish, fzf, zoxide - Integrations wakatime, tailscale - Recommended cargo, starship, uv, direnv, paru, yay, eza, lsd, bat, - btop, dust, duf, prettyping, ov, ripgrep, lazygit, - lazydocker, trash, kitty, wezterm, python3, yt-dlp - - fish-deps - fish-deps install - fish-deps update - fish-deps sync - -### check_fish_deps - - Synopsis: check_fish_deps - Backwards-compatibility alias for `fish-deps status`. - ---- - -## 5.7 System and Monitoring - -### top - - Synopsis: top [args...] - Launches btop as a modern resource monitor. Falls back to system top. - -### swapstat - - Synopsis: swapstat - Displays a colorized memory report: kernel swappiness, zRAM compression - ratio, zRAM device details, and active swap priorities. - -### sbver - - Synopsis: sbver [--brief] - Verifies Secure Boot signatures on all EFI binaries tracked by sbctl. - Color-codes results: green checkmark (verified), red X (unsigned). - Prints a pass/fail summary. - - --brief Suppress per-file output, show only the summary - - sbver - sbver --brief - -### ports - - Synopsis: ports - Lists active TCP listeners with lsof, showing port/address without - hostname resolution. - -### screensleep - - Synopsis: screensleep - Turns off the display via KDE PowerDevil's "Turn Off Screen" action, - invoked through busctl. - -### lock - - Synopsis: lock - Locks the current desktop session using loginctl lock-session. - -### sudo-toggle - - Synopsis: sudo-toggle - Toggles the sudo NOPASSWD rule on/off via /etc/sudoers.d/nofail-toggle. - Useful for automated tasks that would otherwise require password entry. - -### limine-edit - - Synopsis: limine-edit - Opens /boot/limine.conf in sudoedit, then automatically re-enrolls the - config hash, runs CachyOS boot hooks, and re-signs Secure Boot files. - Combines the edit and sign steps into a single command. - ---- - -## 5.8 Terminal Management - -### tab - - Synopsis: tab [args...] - Opens a new tab in Kitty (kitty @ launch --type=tab), WezTerm - (wezterm cli spawn), or Konsole. Uses current working directory, - or $cdto if set. - - tab - -### split - - Synopsis: split [-h|-v] [command...] - Opens a new pane in Kitty or WezTerm, optionally running a command. - - -h/--horizontal (default) Split below - -v/--vertical Split to the right - - split - split -v nvim README.md - -### spwin - - Synopsis: spwin [args...] - Spawns a new terminal OS window in Kitty (via spawn-window.sh or - kitty @ launch --type=os-window) or WezTerm (wezterm cli spawn --new-window). - -### detach - - Synopsis: detach [-h] [--version] [args...] - Runs a command fully detached via nohup with stdout/stderr discarded. - The command survives the current session. - - detach rsync -a ./data remote:/backup/ - -### bkg - - Synopsis: bkg [args...] - Launches a command in the background via nohup with output discarded. - Simpler than detach; no version flag. - - bkg firefox - -### ssh - - Synopsis: ssh [args...] - In Kitty, wraps ssh with kitten ssh for better terminal integration - (multiplexing, copy/paste support). Falls back to system ssh elsewhere. - - ssh user@host - ---- - -## 5.9 Clipboard - -### y - - Synopsis: y [text...] - Copies text to the clipboard via wl-copy (Wayland) or xclip (X11). - Reads from stdin if no arguments given. - - y "hello world" - ls | y - cat file.txt | y - -### p - - Synopsis: p [args...] - Outputs clipboard contents to stdout. - - p | grep foo - p > file.txt - -### paste - - Alias for p. Identical behaviour. - ---- - -## 5.10 Network - -### gip - - Synopsis: gip - Fetches and prints both the public IPv4 and IPv6 address via - icanhazip.com. - -### gip4 - - Synopsis: gip4 - Fetches and prints the public IPv4 address. - -### gip6 - - Synopsis: gip6 - Fetches and prints the public IPv6 address. Returns 1 if IPv6 is - unavailable. - -### ping - - Synopsis: ping [args...] - Wraps prettyping with --nolegend. Pass --legend to show the legend. - Falls back to system ping. - - ping google.com - -### qr - - Synopsis: qr [text...] - Generates a UTF-8 QR code from text or stdin. Uses qrencode locally; - falls back to the qrenco.de API. - - qr "https://example.com" - echo "https://example.com" | qr - ---- - -## 5.11 Pager and Logging - -### logs - - Synopsis: logs [-c ] - Interactively browses terminal log files sorted newest-first using fzf. - - -c/--category Filter to: scrollback, paru, or yay - - Keybindings inside the fzf browser: - Enter Open in $PAGER - Ctrl+E Open in $EDITOR - Ctrl+D Delete (with confirmation) - ? Toggle keybind help overlay - - Paru and yay logs open in ov with syntax highlighting and sticky section - headers. Scrollback logs open in ov with per-command sticky prompt headers - based on OSC 133 markers. - - logs - logs -c paru - logs -c scrollback - -### smart_exit - - Synopsis: smart_exit [-n] - Closes the shell session. In Kitty, captures the terminal scrollback to - a timestamped log file in $SCROLLBACK_HISTORY_DIR before exiting. - Automatically prunes the oldest logs when the count exceeds - $SCROLLBACK_HISTORY_MAX_FILES. - - -n/--no-log Exit without saving a scrollback log - - The exit builtin is wired to smart_exit for interactive sessions. - Typing exit or Ctrl+D behaves identically to smart_exit. - - smart_exit - smart_exit --no-log - ---- - -## 5.12 AI and Developer Tools - -### agy - - Synopsis: agy [args...] - Wrapper for the agy Antigravity AI CLI. Before launching, delegates to - agents-init --agents to ensure AGENTS/ is scaffolded and CLAUDE.md is - symlinked to AGENTS/AGENTS.md in the current project, then forwards all - arguments verbatim to the real agy binary. Command shadow (C1): when - __fish_config_op_aliases (or the master) is disabled, the call is - passed through to the real agy binary unchanged. - - agy chat - agy resume - -### antigravity-ide - - Synopsis: antigravity-ide [args...] - Runs the antigravity-ide editor with warnings filtered. - -### agents-init - - Synopsis: agents-init [--agents | --plugins] - Scaffold an AGENTS/ sub-repository for tracking agent specs, plans, specs, - and dev logs. Creates AGENTS/ as a standalone git repo, moves any existing - AGENTS.md into it, and replaces it with a relative symlink (plus - CLAUDE.md -> AGENTS/AGENTS.md so Claude Code picks up the shared agent - instructions). Consolidates plans/ and specs/ directly under AGENTS/ - (merging any legacy docs/plans, docs/superpowers/plans, or old - AGENTS/plugins/ locations into the canonical AGENTS/), creates - AGENTS/devlogs/, and wires docs/superpowers/{plans,specs} symlinks back to - them. Adds managed paths to .gitignore and auto-commits every change inside - the AGENTS/ sub-repo; pulls first when the sub-repo has an upstream. - Fully idempotent: a second run produces no output and no new commits. - Flags: --agents re-runs only the AGENTS.md / symlink step; --plugins - re-runs only the plans/specs/devlogs wiring step. Called automatically by - the claude and agy wrappers on every invocation. - - Structure versioning: each AGENTS/ repo carries a self-contained version - bumper. AGENTS/.version holds MAJOR.MINOR.PATCH (seeded 1.0.0). Committed - git hooks under AGENTS/.agents-tools/ (wired via core.hooksPath) bump it on - every commit: MINOR (resetting PATCH) when the tracked directory set - changes, PATCH otherwise; MAJOR is manual-only. A prepare-commit-msg hook - appends "(vX.Y.Z)" to the commit subject. Downstream tooling can read - AGENTS/.version - a changed MINOR field signals a structure change. Because - core.hooksPath is a single setting, the local override would otherwise - shadow your global hooks; after bumping the version, each shim chains - (execs) to the global/system core.hooksPath hook of the same name so global - pre-commit / prepare-commit-msg hooks (e.g. ggshield, Git LFS) still run. - The script and hooks are shipped from scripts/agents-tools/ and refreshed - when their version marker is stale. - - agents-init - agents-init --agents - agents-init --plugins - -### claude - - Synopsis: claude [args...] - Wrapper for the claude CLI. Before launching, delegates to agents-init - --agents to ensure AGENTS/ is scaffolded and CLAUDE.md is symlinked to - AGENTS/AGENTS.md in the current project, then forwards all arguments - verbatim to the real claude binary. Command shadow (C1): when - __fish_config_op_aliases (or the master) is disabled, the call is - passed through to the real claude binary unchanged. - - claude - claude --resume - -### claude-docs - - Synopsis: claude-docs - Invokes Claude Code to analyze recent repository changes and update - README.md, ensuring all documented features and examples are accurate. - -### claude-pr - - Synopsis: claude-pr - Invokes Claude Code to run the full PR workflow: create branch, - conventional commit, verification, push, and open a PR with a manual - verification checklist. - -### qc - - Synopsis: qc [prompt...] - Quick-chat wrapper around the aichat LLM CLI that defaults to the "cli" - role - a system prompt tuned for concise, terminal-friendly output. On - first use it installs the bundled role by symlinking - scripts/cli-agent.md to $XDG_CONFIG_HOME/aichat/roles/cli.md (creating - the directory if needed). Inherits every aichat flag and tab completion - (--wraps aichat); passing --role/-r overrides the default role, so qc - forwards to aichat unchanged. The function is only defined when aichat - is installed. Run qc --help for aichat's full flag reference with the - command name rewritten to qc. - - qc "how do I list open ports on linux?" - qc -m ollama:llama3 "explain this error" - qc --role coder "refactor this function" - -### superpowers - - Synopsis: superpowers [on|off] [-g] - Enables or disables the Superpowers plugin for Antigravity and Claude - Code at workspace/project scope (default) or user scope (-g/--global). - - superpowers on - superpowers off -g - ---- - -## 5.13 Media and Utilities - -### dng2avif - - Synopsis: dng2avif [-i ] [-o ] [-q ] [-s ] [input.dng] - Converts a DNG raw image to a 10-bit HDR AVIF using an ImageMagick, - ffmpeg, avifenc pipeline with metadata sync via exiftool. - - -i/--input Input file (or positional arg) - -o/--output Output file (default: same name, .avif extension) - -q/--quality Quality 0-100 (default 92) - -s/--speed Encoding speed 0-10 (default 3) - - dng2avif photo.dng - dng2avif -q 85 -s 5 -i shot.dng -o out.avif - -### steam-dl - - Synopsis: steam-dl - Launches Steam under systemd-inhibit, preventing the system from going - idle or sleeping while a download is in progress. - -### spark - - Synopsis: spark [--min=] [--max=] [numbers...] - Renders a Unicode sparkline bar chart for a sequence of numbers. - Reads from stdin if no numbers are given. - - spark 1 1 2 5 14 42 - echo "3 7 2 9 1" | spark - -### yt-dlp - - Synopsis: yt-dlp [args...] URL [URL...] - Wraps yt-dlp, prepending sane defaults: --sponsorblock-remove all, - --embed-subs, --embed-metadata, and --embed-thumbnail. Each default - is suppressed when you already pass that flag, its alias, or its - negation (e.g. --no-embed-thumbnail drops the thumbnail default; - --no-sponsorblock or your own --sponsorblock-remove drops ours). All - other arguments pass through unchanged, and --help falls through to - real yt-dlp. Opinionated component (C1 aliases); when disabled it - passes straight through to the system yt-dlp. - - yt-dlp dQw4w9WgXcQ - yt-dlp --no-embed-thumbnail dQw4w9WgXcQ - ---- - -## 5.14 Miscellaneous - -### config-help - - Synopsis: config-help [SECTION] - config-help [SECTION] --html - config-help [SECTION] --man - config-help -h | --help - - Opens the offline fish shell configuration manual. Without flags, opens - the Markdown source in the best available pager (ov > bat > man > less > - cat). If SECTION is given, jumps to the first heading matching that - keyword (case-insensitive; checks fish-config.index aliases first). - - Flags: - --html / -w Open docs/html/index.html in the default browser. - If SECTION is given, opens at the matching anchor. - Detects the browser via xdg-mime x-scheme-handler/https, - then known binaries, then xdg-open as last resort. - Respects $fish_help_browser and $BROWSER. - --man / -m Open docs/fish-config.1 via man -l directly. - If SECTION is given, jumps to the nearest match. - --help / -h Print usage and navigation key reference. - - config-help keybindings - config-help pkg - config-help --html - config-help pkg --html - config-help --man - config-help pkg --man - - Also available as: help config [SECTION] [FLAGS] - -### open-url - - Synopsis: open-url [-s|--silent] [-v|--verbose] - open-url -h | --help - - Opens a URL or file:// URI in the best available graphical web browser, - backgrounded so it never blocks the terminal. Resolves a real browser - binary rather than deferring to xdg-open, whose MIME dispatch can hand - local text/html files to non-browser apps (e.g. ebook readers). - - Silent by default: prints nothing on success (errors always go to - stderr). Pass --verbose / -v to report which browser is launched; - --silent / -s is accepted for explicitness. - - Resolution order: - 1. $fish_help_browser (explicit override) - 2. $BROWSER (validated; errors if not a command) - 3. xdg-mime default handler for x-scheme-handler/https - 4. First known browser binary found in a built-in list - 5. xdg-open (last resort) - - open-url https://git.rootiest.dev/rootiest/fish-config - open-url "file://$HOME/.config/fish/docs/html/index.html" - - Used internally by config-help --html. - - Typo abbreviation: url-open (expands to open-url on space/enter). - -### repo-open - - Synopsis: repo-open [-p|--print] [-r|--root] - repo-open -h | --help - - Opens the web page for the current repository's `origin` remote in a - browser (via open-url). Deep-links to the current branch when it exists - on the remote — falling back to the remote's default branch (main/master) - otherwise — and to the current sub-directory when run below the repo root. - - The remote URL is normalized from HTTPS and SSH/scp forms - (git@host:owner/repo.git, ssh://…, https://…). The web path layout is - provider-specific; the provider is resolved in order: - - 1. git config browse.provider (per-repo or --global override) - 2. Hostname heuristic (github / gitlab / gitea / bitbucket; - codeberg → gitea) - 3. Default: github-style layout - - Self-hosted hosts the heuristic can't classify (a Gitea/GitLab instance - on a custom domain) need a one-time override: - - git config browse.provider gitea - - Flags: - --print / -p Print the resolved URL instead of opening it. - --root / -r Ignore the current sub-directory; link to the repo root. - --help / -h Show usage. - - repo-open - repo-open --print - repo-open --root - - Typo abbreviation: open-repo (expands to repo-open on space/enter). - -### config-update - - Synopsis: config-update [-h] [-n] [-f] - - Pulls the latest fish configuration from the upstream repository - (https://git.rootiest.dev/rootiest/fish-config.git) into ~/.config/fish. - The remote URL is hard-coded, so this works on fresh clones with no git - remote configured. All git output is suppressed; colored messages report - fetch and merge status. After a successful pull, run `exec fish` to - reload. - - Flags: - --dry-run / -n Fetch and show available commits without applying them. - --force / -f Stash local changes, pull, then restore the stash. - --help / -h Show usage. - - config-update - config-update --dry-run - config-update --force - -### config-settings - - Synopsis: config-settings [-h] - - Opens an interactive TUI for managing fish configuration settings across - four pages, without having to type or remember variable names. Tab cycles - forward through the pages; Shift-Tab cycles backward. - - Universal — opinionated category toggles (C1–C6) + master, persistent (set -U) - Session — the same toggles, current shell only (set -g) - Sponge — sponge history-scrubbing settings: delay, successful exit - codes, purge-only-on-exit, allow-previously-successful, and - extra sensitive variable-name tokens - Paths — scrollback log directory, scrollback max files, the - user-dots path, and the user-dots convenience symlink toggle - (Dots link) - - Toggle rows use ← → (or h/l) along an OFF ← DEFAULT → ON scale; DEFAULT - erases the variable so the master switch / built-in default applies. Value - rows (the path/int/list settings on the Sponge and Paths pages) use Enter to - edit inline; ← / h clears the value back to its default. List rows (e.g. - Extra secret, OK codes) accept values separated by commas and/or whitespace - — "A, B", "A,B" and "A B" all yield the same two entries. Changes apply - immediately. Always available regardless of the __fish_config_opinionated - master state. - - The Sponge and Paths pages always write universal variables — these are - persistent, set-and-forget settings with no per-session scope. Editing a - scrollback row updates both the __fish_scrollback_history_* source-of-truth - variables and the exported SCROLLBACK_HISTORY_* mirrors, so the AUR/tmux/ - zellij log wrappers (which read the exported names) see the change in the - running session. - - The panel adapts to the terminal width automatically, selecting from - four layout tiers (with a 6-column buffer on each side before stepping - up to the next tier) and horizontally centering the box. The panel - redraws within ~0.3 s of a terminal resize with no keypress required. - - COLUMNS >= 90 → 78-wide panel (most detail) - COLUMNS >= 86 → 74-wide panel - COLUMNS >= 82 → 70-wide panel - COLUMNS < 82 → 52-wide panel (default) - - Navigation: - ↑ ↓ / k j Move cursor - ← → / h l Toggle rows: OFF ← DEFAULT → ON - ← / h Value rows: clear to default - Enter Value rows: edit inline (Sponge / Paths pages) - Tab / S-Tab Next / previous page - q / Escape Exit - - Flags: - --help / -h Show usage. - - config-settings - -### config-toggle (deprecated) - - Deprecated alias for config-settings. Prints a deprecation notice to - stderr, then delegates all arguments to config-settings. - - config-toggle - -### bash - - Synopsis: bash [args...] - Switches to bash, with XDG config applied. On exit, $SHELL is reset - back to fish. - -### bd-pull - - Synopsis: bd-pull - Fetches unlinked Gitea issues and creates local Beads entries, updating - issue titles with the assigned Beads IDs. - Requires $GITEA_TOKEN and $GITEA_URL to be set. - - bd-pull rootiest/fish-config - -### cheat - - Synopsis: cheat [args...] - Displays a colorized cheatsheet using cheat -c, falls back to tldr, - then man. - - cheat tar - cheat git - -### cffetch / ffetch - - Synopsis: cffetch [args...] / ffetch [args...] - Clears the screen and displays system information via fastfetch with - the custom config at ~/.fastfetch.jsonc. Falls back to neofetch. - -### dockup - - Synopsis: dockup [-h] [directory] - Pulls latest Docker images, restarts services in the given Docker - Compose project, and prunes dangling images. - - dockup ~/myapp - -### joplin - - Synopsis: joplin [args...] - Runs the Joplin CLI with Node.js deprecation warnings suppressed. - - joplin ls - -### ld - - Synopsis: ld - Launches lazydocker targeting the currently active Docker context, - detected via docker context inspect. - -### replay - - Synopsis: replay - Runs Bash commands and replays any resulting changes to environment - variables, aliases, and the working directory back into the current - Fish session. Useful for sourcing Bash scripts. - - replay "source ~/.bashrc" - replay "export FOO=bar" - -### kitty-logging - - Synopsis: kitty-logging [install|uninstall|status|dismiss] [-h] - - Manages the Kitty scrollback watcher that powers C5 logging. Ships a - canonical watcher and symlinks it into the Kitty config directory (so it - always tracks the source), wiring it into kitty.conf through a - sentinel-marked managed block. Commenting out any conflicting watcher line - avoids double-capture. - - Commands: - install Symlink the watcher and add the managed block - uninstall Remove the managed block and the watcher symlink - status Show wiring, installed watcher version, and C5 state - dismiss Stop the per-session setup reminder - - Runtime capture stays governed by the C5 .logging_disabled sentinel, so - disabling __fish_config_op_logging makes the watcher inert without - uninstalling. Install affects new Kitty windows only. - - Example: - kitty-logging install - kitty-logging status - -### tmux-clean - - Synopsis: tmux-clean - Kills all detached (unattached) tmux sessions, leaving attached ones - running. - -### wake-lock - - Synopsis: wake-lock [args...] - Runs a command under systemd-inhibit, preventing the system from going - idle or sleeping until the command completes. - - wake-lock rsync -avz src/ dest/ - ---- diff --git a/docs/wiki/6-dependency-catalog.md b/docs/wiki/6-dependency-catalog.md deleted file mode 100644 index 2b14535..0000000 --- a/docs/wiki/6-dependency-catalog.md +++ /dev/null @@ -1,69 +0,0 @@ -# 6. DEPENDENCY CATALOG - -**Sections:** [Index](index.md) | [1. Configuration Variables](1-configuration-variables.md) | [2. Path Setup](2-path-setup.md) | [3. Key Bindings](3-key-bindings.md) | [4. Abbreviations](4-abbreviations.md) | [5. Functions Reference](5-functions-reference.md) | **6. Dependency Catalog** | [7. Customization](7-customization.md) | [8. Fisher Plugins](8-fisher-plugins.md) | [9. Installation](9-installation.md) | [10. Personalization](10-personalization.md) | [11. Viewing This Manual](11-viewing-this-manual.md) - ---- - -fish-deps manages these tools. Run `fish-deps` to check status, or -`fish-deps install` to install missing ones. - -## Required - - fish Fish shell >= 4.0 - fzf Fuzzy finder - zoxide Smart cd with frecency - -## Integrations - - wakatime Developer time tracking - tailscale Mesh VPN client - -## Recommended - - cargo Rust toolchain (via rustup); used by fish-deps to install - Rust-based tools and to build fish from source. All paths - are gated on type -q cargo and degrade gracefully. - starship Cross-shell prompt; loaded via type -q starship guard. - Without it the Catppuccin nim-style fallback prompt activates. - uv Python package and project manager (Astral); used by the - fish-from-source build path in fish-deps. All consumers - degrade gracefully without it. - direnv Per-directory environment loading; integration is fully - guarded with type -q direnv. Without it the direnv hook - is simply not loaded and auto-venv activates normally. - paru AUR helper (Arch only; preferred); guarded throughout — - non-Arch systems silently skip AUR-specific paths. - yay AUR helper (Arch only; fallback to paru); same guards apply. - eza Modern ls replacement - lsd ls replacement (fallback to eza) - bat Syntax-highlighted cat - btop Modern resource monitor - dust Disk usage tree (Rust) - duf Disk usage/free overview - prettyping Colorized ping wrapper - ov Modern pager (replaces less) - ripgrep Fast line search - lazygit Terminal git UI - lazydocker Terminal docker UI - trash Safe delete (trash-cli) - kitty GPU-accelerated terminal (primary) - wezterm GPU-accelerated terminal (alternative) - python3 Standalone interpreter — used by the paru/yay log cleaner. - Note: uv does not provide python3 on PATH, and Arch's base - does not include it, so it is listed separately. All - consumers degrade gracefully without it. - yt-dlp Video/media downloader; backs the yt-dlp wrapper function. - Optional — the wrapper falls back to the system yt-dlp and - the rest of the config works without it. - -## Install Methods - -The install priority for each tool: - - cargo Rust tools (eza, lsd, bat, dust, ov, ripgrep, trashy, zoxide, - starship) — always gets the latest crate version - system PM paru / apt / brew / dnf / etc. — for tools without a crate - git clone fzf — installed from GitHub to ~/.fzf/ - curl starship installer, fisher bootstrap, uv installer - ---- diff --git a/docs/wiki/7-customization.md b/docs/wiki/7-customization.md deleted file mode 100644 index 96ab41b..0000000 --- a/docs/wiki/7-customization.md +++ /dev/null @@ -1,434 +0,0 @@ -# 7. CUSTOMIZATION - -**Sections:** [Index](index.md) | [1. Configuration Variables](1-configuration-variables.md) | [2. Path Setup](2-path-setup.md) | [3. Key Bindings](3-key-bindings.md) | [4. Abbreviations](4-abbreviations.md) | [5. Functions Reference](5-functions-reference.md) | [6. Dependency Catalog](6-dependency-catalog.md) | **7. Customization** | [8. Fisher Plugins](8-fisher-plugins.md) | [9. Installation](9-installation.md) | [10. Personalization](10-personalization.md) | [11. Viewing This Manual](11-viewing-this-manual.md) - ---- - -## Machine-local Configuration - -Place machine-specific settings that should not be committed to git in: - - $__fish_user_dots_path/local.fish - -`__fish_user_dots_path` defaults to `~/.config/.user-dots/fish`. Set a -custom location with: - - set -U __fish_user_dots_path /path/to/your/dots/fish - -Typical uses: additional PATH entries, local aliases, hostname-specific env -vars, work-specific tool configs. - -For convenience, a git-ignored `user-dots` symlink in the fish config -directory tracks `$__fish_user_dots_path` so the overlay can be browsed from -`~/.config/fish/`. It is created if missing and repointed if the path changes. -Opt out by setting `__fish_user_dots_symlink` to a falsy value, or toggling -"Dots link" off on the config-settings Paths page — this stops generation and -removes any existing link. It only ever manages a symlink and never clobbers a -real file or directory at that path. - -## Secrets and API Keys - - $__fish_user_dots_path/secrets.fish - -Store API tokens, GPG keys, private credentials here. This file is never -committed. It is sourced by local.fish directly, not by config.fish. - -`local.fish` is sourced at the end of config.fish on every interactive -session, so it and its companion secrets.fish can override anything set -earlier. - -## Overriding Configuration Variables - -Any variable set in local.fish after the main config loads takes effect. -Example: to increase the scrollback history limit: - - # in local.fish - set -gx SCROLLBACK_HISTORY_MAX_FILES 200 - -## Fish Universal Variables - -Some settings (fzf colors, theme) are stored in fish_variables via -`set -U`. These are machine-local and git-ignored. Do not commit -fish_variables. - -## Opinionated Components (Minimal Mode) - -Every opinionated piece of this config is active by default but can be -switched off through six category opt-out variables, each evaluated via -__fish_variable_check. Set a variable to any falsy value (0, false, no, -off, n) to disable its category; erase it or set a truthy value (1, true, -yes, on, y) to re-enable. Unset means enabled. - -An explicit per-category truthy value takes precedence over the master -switch: setting __fish_config_opinionated=0 disables all unset categories, -but a category with an explicit truthy value remains enabled regardless. - - Variable Disables - ------------------------------ ------------------------------------ - __fish_config_op_aliases Command shadows and flag injection: - ls->eza, cat->bat, cd->zoxide, - rm->trash, less->ov, top->btop, - ping->prettyping, ssh->kitten, - du->duf/dust, mkdir/bash wrappers, - history timestamps, grep/cp/mv/wget - flag injection, help intercept, claude - AGENTS.md auto-link - __fish_config_op_autoexec Startup side-effects: Fisher - bootstrap, theme apply, paru/yay - wrapper generation, auto venv - activation, WakaTime hook - __fish_config_op_overrides Key and env overrides: Vi mode, - exit->smart_exit, PAGER/MANPAGER, - CDPATH, bang-bang system, autopair, - puffer, starship prompt, theme - colors, FZF_DEFAULT_OPTS, right - prompt - __fish_config_op_integrations Terminal/tool coupling: Kitty/ - WezTerm window abbreviations, done - notifications, spwin/tab/split, - hist, logs, upgrade, WakaTime - __fish_config_op_logging Logging & capture: scrollback - capture on exit, paru/yay AUR log - wrappers, Kitty watcher capture; - sentinel file coordinates - cross-process state - __fish_config_op_greeting Greeting & first-run UI: per-session - fish_greeting override (defines empty - function late in config.fish to - suppress distro greetings such as - CachyOS fastfetch); first-run welcome - banner in conf.d/first_run.fish - -Examples: - - # Disable command shadows only (rm becomes plain rm again): - set -U __fish_config_op_aliases off - - # Full minimal mode — disable all six categories at once: - set -U __fish_config_opinionated 0 - - # Re-enable everything: - set -Ue __fish_config_opinionated - - # Minimal mode but keep the greeting: - set -U __fish_config_opinionated 0 - set -U __fish_config_op_greeting 1 - # (erase both to go back to full-flavor defaults) - -For an interactive alternative to setting these variables by hand, run -config-settings — a full-screen TUI that flips any category (including C5 -logging) on or off, per session or universally. See its entry in Section 5. - -Notes: - - - Command shadows (rm, cat, ls, ...) react immediately; conf.d-level - components (bindings, prompt, abbreviations, hooks) take effect in - new shells. - - With aliases disabled, rm falls back to bare `command rm` — files - are deleted permanently, not trashed. - - Disabled integration commands (spwin, tab, split, hist, logs, - upgrade) print an error naming the variable that disabled them. - - On CachyOS, the distro fish config's own aliases, history override, - and bang-bang bindings are stripped per category as well. - -### Component Reference - -The following tables detail every component in each category. Use this -reference to understand exactly which behaviors change when you toggle a -category variable. - -#### C1 — Command Shadows - -Disabling __fish_config_op_aliases restores standard system behavior for -all of these commands. - - Command / Alias Active behavior Disabled fallback - ─────────────────────────────────────────────────────────────────────────── - ls eza -l -a --icons --hyperlink system ls - cat bat syntax-highlighted; dirs → ls /usr/bin/cat - cd zoxide frecency-based navigation fish builtin cd - rm moves files to trash (recoverable) command rm (permanent) - less $PAGER → ov → less → more → cat system less - du duf (disk overview) or dust (dir tree) system du - top btop resource monitor system top - ping prettyping --nolegend animation system ping - ssh kitten ssh in Kitty terminal system ssh - rg rg --hyperlink-format=kitty system rg - mkdir verbose path-tree display on creation mkdir -p silently - bash XDG bashrc + $SHELL reset on exit system bash - history timestamps prepended to every entry fish builtin history - cp / mv forced -i confirmation prompt cp / mv unmodified - wget forced --continue (resume downloads) system wget - grep/fgrep/egrep forced --color=auto system grep variants - dir / vdir forced --color=auto system dir / vdir - help config intercepts "help config" → config-help fish builtin help - claude auto-links AGENTS.md as CLAUDE.md before launch command claude - edit multi-editor launcher (GUI/term + fallbacks) $EDITOR/nvim/nano/vi - -When C1 is disabled, `rm` uses bare `command rm` with no wrapper — files -are permanently deleted, not trashed. There is no intermediate safety net. - -#### C2 — Startup Side-Effects - -These run automatically without any user action. Disabling -__fish_config_op_autoexec prevents all of them. - - Component Trigger What it does - ─────────────────────────────────────────────────────────────────────────── - Fisher bootstrap First shell only Downloads and installs fisher - Fisher update After bootstrap Installs all fish_plugins entries - Catppuccin Mocha theme First shell only Applies theme via fish_config - paru wrapper Every startup Writes ~/.local/bin/paru wrapper - yay wrapper Every startup Writes ~/.local/bin/yay wrapper - Python venv activation On every cd Sources .venv/bin/activate.fish - WakaTime command hook On every command Reports to WakaTime API - Auto-pull fast-forward On entering a repo Background ff-only git pull - user-dots symlink Every startup Links $__fish_config_dir/user-dots - to $__fish_user_dots_path - -When C2 is disabled: no Fisher install, no theme application, no paru/yay -wrapper generation, no automatic venv activation, no WakaTime reporting, -no auto-pull (the PWD handler is never registered), and the user-dots -convenience symlink is not created. The symlink is git-ignored and only ever -managed as a symlink — a real file or directory at that path is left untouched. -The symlink has its own opt-out independent of C2: set __fish_user_dots_symlink -to a falsy value (or toggle "Dots link" off on the config-settings Paths page) -to stop generating it and remove any existing link — honoured even when C2 is -enabled. Managed by the __fish_user_dots_link helper. -The first-run completion marker (__fish_config_first_run_complete) is still -set so the init does not re-run on subsequent shells. - -Python venv activation fires on every directory change. If a directory uses -direnv (.envrc present), direnv takes priority and auto-venv is skipped for -that directory. - -Auto-pull fast-forwards opted-in repositories in the background when you cd -into them. The fish-config repo is always covered; other repos are added with -the `auto-pull` command (see its entry in the functions reference). It only -ever fast-forwards a clean repo whose branch has an upstream — never rebases, -merges, or overwrites work — so it is a no-op on dirty trees, divergent -branches, or repos without a remote. The handler fires once per repo entry -(not on every sub-directory cd). The registry is machine-local at -`$__fish_user_dots_path/auto-pull.list` (defaults to `~/.config/.user-dots/fish/auto-pull.list`) and is never committed. - -#### C3 — Key and Environment Overrides - -These change fundamental shell behavior: how keys work, which pager opens, -and what the prompt looks like. Disabling __fish_config_op_overrides removes -all of them. - - Override What it replaces or sets - ─────────────────────────────────────────────────────────────────────────── - Vi mode fish_vi_key_bindings replaces default Emacs mode - exit → smart_exit exit wrapper that captures scrollback before closing - PAGER=ov ov used by git, man, and all $PAGER-aware tools - MANPAGER=bat pipeline man pages rendered with syntax highlighting - CDPATH=. ~/projects ~ bare dir names resolve against ~/projects and ~ - Bang-bang system ! and $ keys expand history; !^, !*, !-N, !?str?, - ^old^new abbreviations; six expand_bang_* helpers - Autopair ( [ { " ' auto-close to (), [], {}, "", '' - Puffer key intercepts . ! $ * keys intercepted for smart expansion - Starship prompt fish_prompt replaced by Starship + OSC 133 markers - Catppuccin colors 30+ fish_color_* variables set to Mocha palette - FZF_DEFAULT_OPTS FZF themed to Catppuccin Mocha colors - Right prompt fish_right_prompt: exit code (on failure) + dim timestamp; always rendered; Docker context added when starship+C3 active - -The bang-bang system spans key_bindings.fish, abbr.fish, puffer.fish, and -six expand_bang_*.fish functions. All are gated together — disabling C3 -removes the entire bang-expansion system at once. - -When C3 is disabled, `exit` falls back to `builtin exit` with no scrollback -capture, no Kitty IPC, and no file I/O on exit. The scrollback capture block -is independently controlled by C5 (see below). - -#### C4 — Terminal and Tool Integration - -These features couple the shell to specific external tools. Disabling -__fish_config_op_integrations disables all of them. - - Component Requires - ─────────────────────────────────────────────────────────────────────────── - ~60 Kitty/WezTerm abbrs Active Kitty or WezTerm session - (:w, :wv, :wh, :t, etc.) - Done desktop notifications Graphical desktop with a notification daemon - spwin Kitty or WezTerm - tab Kitty, WezTerm, or Konsole - split Kitty or WezTerm - hist fzf + wl-copy (Wayland clipboard) - logs fzf + ov; reads from ~/.terminal_history/ - upgrade paru or yay (Arch Linux only) - WakaTime hook wakatime CLI and a configured API key - -Disabled integration commands (spwin, tab, split, hist, logs, upgrade) print -a colored error to stderr naming the variable that disabled them rather than -silently failing. - -#### C5 — Logging and Capture - -Five components capture shell output to disk. Disabling -__fish_config_op_logging skips all capture and removes the logging wrappers. - - Component What it captures - ─────────────────────────────────────────────────────────────────────────── - Scrollback capture Terminal session output saved to: - ~/.terminal_history/scrollback_YYYY-MM-DD_HH-MM-SS.log - tmux pane capture Continuous pane stream via pipe-pane, saved to: - ~/.terminal_history/tmux_-w-p_YYYY-MM-DD_HH-MM-SS.log - zellij pane capture Pane scrollback snapshot on shell exit, saved to: - ~/.terminal_history/zellij_-p_YYYY-MM-DD_HH-MM-SS.log - paru wrapper All paru/AUR output captured to: - ~/.terminal_history/paru_YYYY-MM-DD_HH-MM-SS.log - yay wrapper All yay/AUR output captured to: - ~/.terminal_history/yay_YYYY-MM-DD_HH-MM-SS.log - Kitty watcher watcher.py captures scrollback when Kitty closes - -The tmux capture starts automatically when fish launches inside any tmux -pane ($TMUX is set). It uses tmux's native pipe-pane to stream all pane -output directly to disk without an intermediate process. Each fish shell -session gets its own log file; a new log is created on each shell start -(including exec fish and new splits). Before each new log, the oldest -tmux_*.log files are pruned (by modification time) to keep the total within -SCROLLBACK_HISTORY_MAX_FILES, matching the paru/yay wrapper behaviour. - -The zellij capture works differently: Zellij has no live output-streaming -facility like pipe-pane, so the log is taken as a one-shot snapshot when the -shell exits, via `zellij action dump-screen --full --ansi` (the --ansi flag -preserves color). The dump is captured on the fish process's stdout and -written to the log file by fish itself (not via `--path`, which would make the -zellij server write the file). A fish_exit handler (registered whenever -$ZELLIJ is set) writes the pane's full scrollback and then prunes old -zellij_*.log files the same way. Because the capture happens at exit, toggling -__fish_config_op_logging takes effect on the next exit with no restart or -sentinel coordination needed — the C5 guard is re-checked when the handler -fires. - -LIMITATION — zellij capture only fires on a clean shell exit (typing `exit`, -Ctrl-D, or a logout), because that is when the fish_exit handler runs. It does -NOT capture when you close a pane or quit zellij through zellij itself: - - - Closing a pane signals the shell and tears the pane down concurrently, so - even if the handler runs, `dump-screen` may find the pane buffer already - gone. - - Quitting zellij kills the zellij server, and `dump-screen` needs a live - server to read from — there is nothing left to snapshot. - -This is a structural difference from tmux, NOT a bug. tmux streams pane output -to disk continuously via pipe-pane, so whatever was printed is already saved -no matter how the pane dies. Zellij can only snapshot, and the only reliable -snapshot point from the shell is a clean exit. To guarantee a zellij pane is -logged, end the session with `exit` or Ctrl-D rather than zellij's close-pane -or quit actions. - -The Kitty watcher is managed by the kitty-logging command: it symlinks the -watcher (fish-config-watcher.py) into the Kitty config directory and wires it -into kitty.conf via a managed block. Inside Kitty, a non-blocking -per-session reminder points first-time users at `kitty-logging install` until -they install or run `kitty-logging dismiss`. Install affects new Kitty windows -only; runtime disable is still handled by the .logging_disabled sentinel. - -Logging coordination via sentinel file - -C5 uses a sentinel file to synchronize state between the shell and -out-of-process components (the Kitty watcher and all running shells): - - ~/.config/fish/.logging_disabled - -Disabling __fish_config_op_logging: - 1. Creates the sentinel immediately in every open shell. - 2. Removes ~/.local/bin/paru and ~/.local/bin/yay logging wrappers; - bare /usr/bin/paru and /usr/bin/yay are used instead. - 3. Kitty's watcher.py reads the sentinel on each save attempt and - skips capture — no Kitty restart required. - 4. smart_exit stops saving scrollback logs. - 5. Stops tmux pipe-pane capture in every open fish shell inside tmux. - -Re-enabling __fish_config_op_logging: - 1. Removes the sentinel in every open shell. - 2. Regenerates paru/yay logging wrappers in ~/.local/bin/. - 3. Kitty watcher resumes capture on the next session exit. - 4. Restarts tmux pipe-pane capture in every open fish shell inside tmux. - -Changes propagate to all running shells through an event handler that fires -whenever __fish_config_op_logging changes — no shell restart needed. - -Note: C3 and C5 compose independently. C3 controls whether the smart_exit -wrapper is active at all; C5 controls only the scrollback-capture block -inside it. With C3 disabled, exit is plain builtin exit regardless of C5. - -#### C6 — Greeting and First-Run UI - - Component What it shows - ─────────────────────────────────────────────────────────────────────────── - First-run welcome banner One-time message on first interactive session - fish_greeting override Empty function defined late in config.fish to - suppress distro greetings (e.g. CachyOS sets - fish_greeting to fastfetch by default) - -When C6 is disabled, no greeting is printed by this config. Any greeting -set by the distro or other configs runs normally — this config simply does -not override it. - -## Prompt and Theme - -### Starship - -The primary prompt is Starship, initialized by conf.d/starship.fish. -Configure it via ~/.config/starship.toml. - -conf.d/starship.fish defines a fish_prompt wrapper that only activates when -starship is in PATH. It emits OSC 133;A (prompt start) immediately before -Starship renders and OSC 133;B (input start) immediately after, placing both -markers on the prompt line itself. This allows ov to use them as sticky -section headers when browsing scrollback logs. Without Starship, fish's -built-in prompt handles these markers automatically. - -### Catppuccin Fallback Prompt - -When Starship is absent or C3 overrides are disabled, a built-in nim-style -two-line prompt activates from functions/fish_prompt.fish. No external -dependencies — fish builtins only. - -Layout: - - ┬─[user@host:~/path] (main) - ╰─>$ - -Elements: - - user Yellow (Catppuccin Yellow); red if root - @host Blue (local) or Teal (SSH) - ~/path prompt_pwd abbreviation (Catppuccin Text) - (main) Current git branch in Catppuccin Pink; omitted outside repos - ─[V:name] Active Python venv basename; omitted when none - ─[N/I/R/V] Vi-mode indicator when vi bindings are active - ┬─ / ╰─> Connector lines: Catppuccin Green on success, Red on failure - -The right prompt (fish_right_prompt.fish) always renders, regardless of C3 -state. On failure it shows a red ✘ and the exit code; on success it shows -only the dim timestamp. When starship is installed and C3 is enabled, the -active Docker context is also shown (if non-default): - - ✘ 1 󰡨 myctx Fri Jun 12 00:51:21 2026 ← failed, starship+C3 active - ✘ 1 Fri Jun 12 00:51:21 2026 ← failed, fallback prompt - Fri Jun 12 00:51:21 2026 ← success (no ✘) - -### FZF - -FZF is themed to Catppuccin Mocha via FZF_DEFAULT_OPTS set in -integrations/fzf.fish. The colors applied: - - Background: #1E1E2E (base) #313244 (surface0) - Foreground: #CDD6F4 (text) - Highlights: #F38BA8 (red) #CBA6F7 (mauve) #B4BEFE (lavender) - -To customize, override FZF_DEFAULT_OPTS in local.fish. - -### Catppuccin Mocha Syntax Highlighting - -The Catppuccin Mocha theme ships with this config in themes/ and is applied -on first run via `conf.d/first_run.fish`. Colors are stored in fish_variables -(universal). To switch variants, install a different theme from themes/: - - fish_config theme save "Catppuccin Latte" - ---- diff --git a/docs/wiki/8-fisher-plugins.md b/docs/wiki/8-fisher-plugins.md deleted file mode 100644 index 2b0e12c..0000000 --- a/docs/wiki/8-fisher-plugins.md +++ /dev/null @@ -1,103 +0,0 @@ -# 8. FISHER PLUGINS - -**Sections:** [Index](index.md) | [1. Configuration Variables](1-configuration-variables.md) | [2. Path Setup](2-path-setup.md) | [3. Key Bindings](3-key-bindings.md) | [4. Abbreviations](4-abbreviations.md) | [5. Functions Reference](5-functions-reference.md) | [6. Dependency Catalog](6-dependency-catalog.md) | [7. Customization](7-customization.md) | **8. Fisher Plugins** | [9. Installation](9-installation.md) | [10. Personalization](10-personalization.md) | [11. Viewing This Manual](11-viewing-this-manual.md) - ---- - -Fisher is bootstrapped automatically on the **first interactive session** via -`conf.d/first_run.fish`. This also applies the Catppuccin Mocha theme and -prints a one-time welcome message (gated by __fish_config_op_greeting; set -it to 0 to suppress). Subsequent sessions skip all first-run logic with zero -overhead. - -To re-trigger first-run initialization (e.g., after a fresh install or for -testing), run: - - set -Ue __fish_config_first_run_complete - -Then open a new shell. - -## Fisher-Managed Plugins - -The following plugins are fully managed by Fisher. Their files are installed -into the repo directory by Fisher and are listed in `.gitignore` — do not -commit them. Fisher installs and updates them automatically. - - jorgebucaran/fisher Plugin manager itself - meaningful-ooo/sponge Remove failed commands from history - -## Sponge History Filtering - -Sponge removes failed commands from history and, via conf.d/sponge_privacy.fish, -also filters privacy-sensitive commands through three layers: - -Layer 1 — Static patterns (universal, persistent across sessions): -Commands matching any of these structural signatures are never recorded: - - --password / --token / --passphrase / --api-key flags with values - Inline env assignments: GITHUB_TOKEN=xxx, MY_API_KEY=abc - Fish set with sensitive names: set -gx GITHUB_TOKEN xxx - URLs with embedded credentials: https://user:pass@host - HTTP Authorization headers: curl -H "Authorization: ..." - Basic auth flags: curl -u user:pass - sshpass, docker login -p, openssl -passin/-passout - -Layer 2 — Dynamic secret values (session globals, refreshed each login): -On the first prompt, after secrets.fish has loaded, the literal values of -all exported variables whose names suggest credentials (TOKEN, PASSWORD, -SECRET, API_KEY, etc.) are collected, regex-escaped, and added as a -session-scoped overlay. Because globals shadow universals in Fish, the -combined list is what sponge sees. Rotating a token takes effect on the -next login automatically. - -Layer 3 — Per-command filter (sponge_filter_secrets): -Catches credentials in variables exported after login, such as tokens -sourced from a project .env file mid-session. - -To add your own persistent patterns: - - set -U -a sponge_regex_patterns 'your-regex-here' - -To mark additional variable NAMES as credential-bearing (so Layer 2 scrubs -their values), add name tokens — via `config-settings` → Sponge, or directly: - - set -U -a __fish_sponge_extra_sensitive ACME_API VAULT_PW - -Tokens are folded into the Layer 2 name match case-insensitively as substrings, -so ACME_API also covers ACME_API_KEY. (The match uses `--entire` to return the -full variable name, so partial-name tokens dereference the right value.) - -The `config-settings` Sponge page also surfaces sponge's own tuning variables — -sponge_delay, sponge_successful_exit_codes, sponge_purge_only_on_exit, and -sponge_allow_previously_successful — so they can be changed without typing -variable names. - -## Bundled Plugin Functionality - -The remaining plugin functionality is bundled directly with this config rather -than managed through Fisher. The bundled versions include customizations for -Fish 4.x compatibility and improved behavior that differ from their upstream -releases. Installing them through Fisher would overwrite these customizations. - -Bundled components and their upstream origins: - - catppuccin/fish → themes/ + conf.d/theme.fish - PatrickF1/fzf.fish → functions/_fzf_*.fish + conf.d/fzf.fish - franciscolourenco/done → conf.d/done.fish - jorgebucaran/autopair.fish → functions/_autopair_*.fish + conf.d/autopair.fish - nickeb96/puffer-fish → functions/_puffer_fish_*.fish + conf.d/puffer.fish - -Do not run `fisher install` for these — it will overwrite the customized -versions. To update their behavior, edit the relevant bundled files directly. - -## fish_plugins Manifest - -The `fish_plugins` file at the config root: - - jorgebucaran/fisher Plugin manager itself - meaningful-ooo/sponge Remove failed commands from history - -To update all Fisher-managed plugins, run `fisher update` or `fish-deps -update` which calls it as its first step. - ---- diff --git a/docs/wiki/9-installation.md b/docs/wiki/9-installation.md deleted file mode 100644 index b220bdf..0000000 --- a/docs/wiki/9-installation.md +++ /dev/null @@ -1,39 +0,0 @@ -# 9. INSTALLATION - -**Sections:** [Index](index.md) | [1. Configuration Variables](1-configuration-variables.md) | [2. Path Setup](2-path-setup.md) | [3. Key Bindings](3-key-bindings.md) | [4. Abbreviations](4-abbreviations.md) | [5. Functions Reference](5-functions-reference.md) | [6. Dependency Catalog](6-dependency-catalog.md) | [7. Customization](7-customization.md) | [8. Fisher Plugins](8-fisher-plugins.md) | **9. Installation** | [10. Personalization](10-personalization.md) | [11. Viewing This Manual](11-viewing-this-manual.md) - ---- - -This configuration is managed as a git repository. To deploy on a new machine: - - mv ~/.config/fish ~/.config/fish.bak # back up any existing config - git clone https://git.rootiest.dev/rootiest/fish-config.git ~/.config/fish - -Then open a new Fish shell. Fisher installs automatically on first launch -and the Catppuccin Mocha theme is applied. All other plugin functionality is -bundled directly with this config and requires no additional installation. - -## Return Sentinel - -config.fish ends with a return sentinel guard. Any lines appended after it by -a tool's setup command (starship init fish | source, zoxide init fish | source, -etc.) will have no effect. All integrations are managed via conf.d/ files. - -If a new tool's shell integration appears to do nothing, check whether its -setup command appended an init line below the sentinel and create a dedicated -conf.d/.fish instead. - -## Updating - -Pull the latest changes from the upstream repository without needing a -configured git remote: - - config-update Fetch and apply the latest commits from upstream - config-update --dry-run Preview available changes without applying them - config-update --force Stash local changes, pull, then restore the stash - -The remote URL (https://git.rootiest.dev/rootiest/fish-config.git) is -hard-coded, so this works on a fresh clone with no origin configured. All -git output is suppressed. Run exec fish after a successful update to reload. - ---- diff --git a/docs/wiki/index.md b/docs/wiki/index.md deleted file mode 100644 index ae4c0f6..0000000 --- a/docs/wiki/index.md +++ /dev/null @@ -1,79 +0,0 @@ -# Fish Shell Configuration - -A production-grade Fish shell configuration targeting Fish 4.x. It provides: - -- Drop-in replacements for common Unix tools (ls, cat, rm, du, ping, less) -- Deep Kitty and WezTerm terminal integration: tab/window/pane management from - the command line -- Automatic session logging: terminal scrollback, tmux/zellij panes, and - paru/yay output captured to ~/.terminal_history (on by default; see below) -- Automatic Python virtualenv activation on directory change -- Cross-platform package management via pkg and fish-deps -- AI session helpers for Claude Code and Antigravity -- Catppuccin Mocha color theme throughout - -> **CAUTION - SESSION LOGGING IS ON BY DEFAULT** -> -> This configuration silently records terminal output to `~/.terminal_history`: -> Kitty scrollback on window close, live tmux pane streams, zellij pane -> snapshots on exit, and full paru/yay output. These logs can contain command -> output, file contents, and secrets printed to the terminal. Nothing leaves -> your machine, but the files persist locally. -> -> - Disable all logging with: `set -U __fish_config_op_logging off` -> - Prefer a menu? Run the interactive picker: `config-settings` -> - See Section 7 (C5 - Logging and Capture) for the full breakdown. - -The configuration is split across: - - config.fish Main entry point; sets env vars and PATH - conf.d/ - abbr.fish All abbreviations - autopair.fish Auto-pair brackets and quotes (bundled from jorgebucaran/autopair.fish) - cheat.fish cheat.sh tab completions - done.fish Desktop notifications for long commands - first_run.fish One-time init: Fisher bootstrap, theme, welcome - key_bindings.fish Custom key bindings and Vi mode - logging-events.fish C5 --on-variable event handlers; syncs logging state at startup - kitty-watcher-reminder.fish C5 per-session reminder to set up the Kitty watcher - paru-wrapper.fish Auto-generates ~/.local/bin/paru logging wrapper - puffer.fish !! / !$ / ./ expansion (bundled from nickeb96/puffer-fish) - tmux-logging.fish C5 starts tmux pipe-pane capture when fish runs inside tmux - zellij-logging.fish C5 fish_exit handler dumping zellij pane scrollback on exit - sponge_privacy.fish Sponge privacy patterns; filters credentials from history - starship.fish fish_prompt with OSC 133 shell-integration markers - tailscale.fish Tailscale CLI tab completions - theme.fish Catppuccin syntax highlight colors - tricks.fish PATH, bang-bang helpers, bat man pages, aliases - wakatime.fish WakaTime shell hook - yay-wrapper.fish Auto-generates ~/.local/bin/yay logging wrapper - zoxide.fish Zoxide z/zi integration; overrides cd - functions/ Custom functions, one per file, autoloaded - completions/ Tab completion scripts - integrations/ - fzf.fish FZF Catppuccin theme and key binding config - scripts/ - clean_progress_log.py Strips paru/yay typescript animations to clean static logs - agents-tools/ AGENTS.md version-bump script and git hooks (wired via core.hooksPath) - docs/ Offline documentation and compiled man page - fish-config.md Primary source manual (terminal-readable) - fish-config.1 Compiled man page (auto-generated by CI) - fish-config.index Section index for help config navigation - html/ Chunked HTML docs (auto-generated by CI) - wiki/ Markdown wiki (auto-generated by CI) - ---- - -## Table of Contents - -- [1. Configuration Variables](1-configuration-variables.md) -- [2. Path Setup](2-path-setup.md) -- [3. Key Bindings](3-key-bindings.md) -- [4. Abbreviations](4-abbreviations.md) -- [5. Functions Reference](5-functions-reference.md) -- [6. Dependency Catalog](6-dependency-catalog.md) -- [7. Customization](7-customization.md) -- [8. Fisher Plugins](8-fisher-plugins.md) -- [9. Installation](9-installation.md) -- [10. Personalization](10-personalization.md) -- [11. Viewing This Manual](11-viewing-this-manual.md) diff --git a/functions/config-help.fish b/functions/config-help.fish index a96f49e..ddb3435 100644 --- a/functions/config-help.fish +++ b/functions/config-help.fish @@ -3,7 +3,7 @@ # SYNOPSIS # config-help [section] -# config-help [section] --html +# config-help --html # config-help [section] --man # config-help --help # @@ -14,14 +14,15 @@ # that matches the keyword. Lookup order: docs/fish-config.index (exact # keyword aliases), then a normalized heading scan as fallback. # When opened with ov a sticky navigation hint is shown at the top of the -# screen. Pass --html / -w to open the pre-built HTML version in the -# default browser, jumping to the matching section anchor when possible. -# Pass --man / -m to open the compiled man page; if a section keyword is -# given, the pager opens at the nearest match. Pass --help or -h for usage. +# screen. Pass --html / -w to open the published documentation website in +# the default browser (deep links to a section aren't supported there — +# use the site's search box). Pass --man / -m to open the compiled man +# page; if a section keyword is given, the pager opens at the nearest +# match. Pass --help or -h for usage. # # ARGUMENTS # section Optional keyword to jump to a matching section heading -# -w, --html Open the offline HTML docs in the default browser +# -w, --html Open the published documentation website in the default browser # -m, --man Open the compiled man page via man -l # -h, --help Print usage and navigation reference, then exit # @@ -35,7 +36,6 @@ # config-help pkg # config-help fish-deps # config-help --html -# config-help keys --html # config-help --man # config-help keys --man # config-help --help @@ -48,8 +48,7 @@ function config-help --description 'Open the offline fish shell configuration ma set -l doc_file "$__fish_config_dir/docs/fish-config.md" set -l idx_file "$__fish_config_dir/docs/fish-config.index" set -l man_file "$__fish_config_dir/docs/fish-config.1" - set -l html_dir "$__fish_config_dir/docs/html" - set -l sitemap "$html_dir/sitemap.json" + set -l site_url "https://fish-config-docs.pages.dev/" # ── Extract section keyword (first non-flag argument) ──────── set -l section_kw "" @@ -97,49 +96,22 @@ function config-help --description 'Open the offline fish shell configuration ma # ── --html / -w ────────────────────────────────────────────── if contains -- --html $argv; or contains -- -w $argv - if not test -f "$html_dir/index.html" + if test -n "$section_kw" + set_color yellow + echo "note: deep links aren't available on the website — opening the site root; use its search box to find '$section_kw'" >&2 + set_color normal + end + + if type -q xdg-open + xdg-open "$site_url" &>/dev/null & + disown + else set_color red - echo "error: HTML docs not found at $html_dir/index.html" >&2 + echo "error: no opener found — visit $site_url" >&2 set_color normal return 1 end - - # Default to the index page; resolve a section fragment when possible. - set -l html_path "index.html" - if test -n "$found_text"; and test -f "$sitemap" - # Convert heading text → pandoc anchor ID: - # lowercase → strip non-alphanumeric (keep spaces and hyphens) - # → spaces to hyphens → collapse runs → strip edge hyphens. - set -l anchor (string lower -- $found_text \ - | string replace -ra '[^a-z0-9 -]' '' \ - | string replace -ra ' +' '-' \ - | string replace -ra -- '-+' '-' \ - | string trim -c '-') - # 1. Sub-section: path stored as "filename.html#anchor" - set -l match (grep -o "\"path\":\"[^\"]*#$anchor\"" "$sitemap" | head -1) - if test -n "$match" - set html_path (string replace -r '"path":"([^"]+)"' '$1' -- $match) - else - # 2. Top-level section: own page — "id":"anchor"..."path":"filename.html" - set -l id_match (grep -o "\"id\":\"$anchor\"[^}]*\"path\":\"[^\"]*\"" "$sitemap" | head -1) - if test -n "$id_match" - set html_path (string replace -r '.*"path":"([^"]+)"' '$1' -- $id_match) - else - set_color yellow - echo "note: no HTML anchor found for '$section_kw' — opening at top" >&2 - set_color normal - end - end - else if test -n "$section_kw" - set_color yellow - echo "note: no section matching '$section_kw' — opening at top" >&2 - set_color normal - end - - set -l page_url "file://$html_dir/$html_path" - - open-url $page_url - return $status + return 0 end # ── --man / -m ─────────────────────────────────────────────── @@ -197,8 +169,8 @@ function config-help --description 'Open the offline fish shell configuration ma echo " Searches docs/fish-config.index for aliases first, then" echo " falls back to a normalized (case- and punctuation-insensitive)" echo " scan of heading lines." - echo " "(set_color yellow)"-w, --html"(set_color normal)" Open the offline HTML docs in the default browser." - echo " If a section keyword is given, opens at the matching anchor." + echo " "(set_color yellow)"-w, --html"(set_color normal)" Open the published documentation website in the default browser." + echo " Deep links aren't supported — use the site's search box." echo " "(set_color yellow)"-m, --man"(set_color normal)" Open the compiled man page via man -l." echo " If a section keyword is given, jumps to the nearest match." echo "" @@ -210,8 +182,7 @@ function config-help --description 'Open the offline fish shell configuration ma echo " "(set_color green)"help config pkg"(set_color normal)" jump to the pkg function entry" echo " "(set_color green)"help config fish-deps"(set_color normal)" jump to fish-deps" echo " "(set_color green)"help config abbreviations"(set_color normal)" jump to Abbreviations section" - echo " "(set_color green)"help config --html"(set_color normal)" open HTML docs in browser" - echo " "(set_color green)"help config keybindings --html"(set_color normal)" open HTML at Key Bindings" + echo " "(set_color green)"help config --html"(set_color normal)" open the documentation website" echo " "(set_color green)"help config --man"(set_color normal)" open compiled man page" echo " "(set_color green)"help config pkg --man"(set_color normal)" open man page at pkg section" echo "" diff --git a/functions/open-url.fish b/functions/open-url.fish index 865bb83..3a7eac5 100644 --- a/functions/open-url.fish +++ b/functions/open-url.fish @@ -32,7 +32,7 @@ # # EXAMPLE # open-url https://git.rootiest.dev/rootiest/fish-config -# open-url -v "file://$HOME/.config/fish/docs/html/index.html" +# open-url -v https://fish-config-docs.pages.dev/ function open-url --description 'Open a URL in the best available web browser' argparse h/help s/silent v/verbose -- $argv or return 1 -- 2.52.0 From ab2f03213b390170b1597f8b20c1ab9833ad61ed Mon Sep 17 00:00:00 2001 From: rootiest Date: Sun, 26 Jul 2026 00:12:33 -0400 Subject: [PATCH 14/15] feat(docs-site): syntax-highlight examples and restyle the site The manual is authored man-page style: every synopsis, example, option table, and description sits in one 4-space-indented block. On the site that renders as a single unhighlighted grey slab, because an indented block declares no language. Split each block into its paragraphs at site-build time and classify them: synopsis and shell examples become ```fish fences, descriptions become real prose, and column-aligned reference tables keep their indentation. 175 blocks now highlight; the 412 lines of genuine tables are left alone. The transform is site-only. docs/manual/** keeps the indented form the pandoc man-page pipeline and config-help depend on, and a test enforces that no fence is ever written back to the SSOT. Also: - Point Expressive Code at the bundled Catppuccin Mocha/Latte themes so code blocks match the palette in catppuccin.css. - Build the functions sidebar group explicitly. `autogenerate` labelled it with the raw directory slug and republished the directory index as a child of the group it already titled, producing the duplicate "Functions Reference" row. - Skip `Synopsis:` lines when deriving card descriptions; they restated the calling convention the card already shows as its title. - Widen the palette: tinted heading levels, inline code, links, card hover accents, aside accents, and table headers. Fixes a bug where _split_entries stripped the leading indentation of an entry's first line, detaching `Synopsis:` from the block it opens. --- docs/build-manual.py | 178 +++++++++++++++++++++++++--- docs/site/astro.config.mjs | 10 ++ docs/site/src/styles/catppuccin.css | 120 +++++++++++++++++++ docs/verify-manual.py | 80 +++++++++++++ 4 files changed, 373 insertions(+), 15 deletions(-) diff --git a/docs/build-manual.py b/docs/build-manual.py index 19dc7e6..64cb612 100644 --- a/docs/build-manual.py +++ b/docs/build-manual.py @@ -71,16 +71,148 @@ def _jsx_attr_escape(value: str) -> str: def _first_sentence(body: str) -> str: - """Extract a one-line description from the start of an entry body.""" + """Extract a one-line description from the start of an entry body. + + `Synopsis:` lines are skipped: they restate the calling convention, + which the card already shows as its title, so using one as the card + description wastes the line. + """ for line in body.split("\n"): line = line.strip() if not line or line.startswith(("#", "```", "|", "-", "*", ">")): continue + if line.startswith("Synopsis:"): + continue m = SENTENCE_RE.match(line) return (m.group(1) if m else line)[:160] return "" +# Commands common enough in this manual that a block whose every line starts +# with one is certainly shell, not prose or a two-column reference table. +SHELL_HEADS = frozenset( + """ + abbr alias apt bg bind brew builtin cargo cat cd chmod code command cp curl + dnf echo end env exec export fg fish fisher for funcsave function git help + if jobs kitty ls man math mkdir mv nvim npm pacman paru pip pip3 pkg printf + python python3 rm set shutdown source string sudo switch systemctl test time + tmux touch trash type wget wezterm while yay zellij zypper + """.split() +) + +SYNOPSIS_PREFIX = "Synopsis:" +INDENT = " " + + +def _is_prose(para: list[str]) -> bool: + """True when a paragraph reads as sentences rather than as code or a table. + + Column-aligned reference tables are the main thing to keep out of a + syntax-highlighted fence, and internal runs of two-or-more spaces are + what distinguishes them from prose. `<` and `{` are excluded because + the emitted paragraph is live markdown, where both would be parsed. + """ + text = " ".join(para) + if "<" in text or "{" in text: + return False + if not para or para[-1].rstrip()[-1:] not in ".:": + return False + return all( + len(line.split()) >= 3 and " " not in line.strip() for line in para + ) + + +def _is_shell(para: list[str], entry_name: str | None) -> bool: + """True when every line of a paragraph looks like a shell command.""" + name_re = ( + re.compile(rf"(? str: + """Render one paragraph of a former indented block. + + `deeper` marks paragraphs carrying their own extra indentation — nested + option tables, whose alignment only survives inside a code block. + """ + if not deeper: + if _is_prose(para): + return "\n".join(line.strip() for line in para) + if _is_shell(para, entry_name): + body = "\n".join(para) + return f"```fish\n{body}\n```" + return "\n".join(INDENT + line for line in para) + + +def _prettify_block(block: list[str], entry_name: str | None) -> str: + """Convert one indented block into fenced code, prose, and tables. + + The manual is authored man-page style: every example, table, and + description sits in a single 4-space-indented block, which renders on + the site as one unhighlighted grey slab. Splitting a block into its + paragraphs recovers the structure the indentation flattened. + """ + lines = [line[len(INDENT) :] if line.startswith(INDENT) else line for line in block] + + out: list[str] = [] + if lines and lines[0].startswith(SYNOPSIS_PREFIX): + synopsis = lines.pop(0)[len(SYNOPSIS_PREFIX) :].strip() + out.append(f"```fish\n{synopsis}\n```") + + para: list[str] = [] + for line in lines + [""]: + if line.strip(): + para.append(line) + continue + if para: + deeper = any(line.startswith(" ") for line in para) + out.append(_render_para(para, entry_name, deeper)) + para = [] + return "\n\n".join(chunk for chunk in out if chunk.strip()) + + +def prettify(body: str, entry_name: str | None = None) -> str: + """Rewrite a body's indented code blocks for the website. + + Site-only: the man page and `config-help` keep reading the untouched + SSOT, where the indented form is exactly what pandoc wants. + """ + out: list[str] = [] + block: list[str] = [] + in_fence = False + + for line in body.split("\n"): + if mt.FENCE_RE.match(line): + in_fence = not in_fence + if not in_fence and (line.startswith(INDENT) or (not line.strip() and block)): + block.append(line) + continue + if block: + while block and not block[-1].strip(): + block.pop() + out.append(_prettify_block(block, entry_name)) + out.append("") + block = [] + out.append(line) + + if block: + while block and not block[-1].strip(): + block.pop() + out.append(_prettify_block(block, entry_name)) + return "\n".join(out) + + def _page_fm(fm: dict) -> dict: """Strip pipeline-only keys from frontmatter destined for the site.""" return {k: v for k, v in fm.items() if k not in PIPELINE_KEYS} @@ -114,7 +246,10 @@ def _split_entries(body: str) -> tuple[str, list[tuple[str, str]]]: for idx, (line_no, title) in enumerate(boundaries): start = line_no + 1 end = boundaries[idx + 1][0] if idx + 1 < len(boundaries) else len(lines) - entry_body = "\n".join(lines[start:end]).strip() + # Strip newlines only: a bare .strip() would eat the leading + # indentation of the entry's first line, detaching the `Synopsis:` + # line from the indented block it opens. + entry_body = "\n".join(lines[start:end]).strip("\n") entries.append((title.strip(), entry_body)) return intro, entries @@ -126,6 +261,7 @@ def build_site(root: Path, out: Path) -> list[dict]: out.mkdir(parents=True) sidebar: list[dict] = [] + functions_group: dict = {} for path, _depth in mt.walk(root): fm, body = mt.parse(path) if not fm.get("site", True): @@ -137,7 +273,7 @@ def build_site(root: Path, out: Path) -> list[dict]: if not is_function_dir: target = out / rel target.parent.mkdir(parents=True, exist_ok=True) - target.write_text(mt.serialize(_page_fm(fm), body)) + target.write_text(mt.serialize(_page_fm(fm), prettify(body))) if rel.name != "index.md": sidebar.append({"label": fm["title"], "link": "/" + rel.stem + "/"}) continue @@ -147,17 +283,16 @@ def build_site(root: Path, out: Path) -> list[dict]: if rel.name == "index.md": target = out / slug_dir / "index.md" target.parent.mkdir(parents=True, exist_ok=True) - target.write_text(mt.serialize(_page_fm(fm), body)) - sidebar.append( - { - "label": fm["title"], - "collapsed": True, - # Starlight >=0.39 rejects a bare `autogenerate` sibling - # of `label` on a top-level group (removed in v0.39.0); - # the autogenerate config must be nested inside `items`. - "items": [{"autogenerate": {"directory": slug_dir}}], - } - ) + target.write_text(mt.serialize(_page_fm(fm), prettify(body))) + # Built explicitly rather than by `autogenerate`, which labels + # each group with its raw directory slug and republishes this + # index as a child of the group it already titles. + functions_group = { + "label": fm["title"], + "collapsed": True, + "items": [{"label": "Overview", "link": f"/{slug_dir}/"}], + } + sidebar.append(functions_group) continue category = re.sub(r"^\d+-", "", rel.stem) @@ -166,6 +301,7 @@ def build_site(root: Path, out: Path) -> list[dict]: intro, entries = _split_entries(body) cards = [] + links = [] for title, entry_body in entries: entry_slug = re.sub(r"[^\w-]+", "-", title.strip().lower()).strip("-") desc = _first_sentence(entry_body) @@ -173,9 +309,10 @@ def build_site(root: Path, out: Path) -> list[dict]: if desc: entry_fm["description"] = desc (cat_dir / f"{entry_slug}.md").write_text( - mt.serialize(entry_fm, entry_body) + mt.serialize(entry_fm, prettify(entry_body, title.split()[0])) ) href = f"/{slug_dir}/{category}/{entry_slug}/" + links.append({"label": title, "link": href}) safe_title = _jsx_attr_escape(title) safe_desc = _jsx_attr_escape(desc) cards.append( @@ -193,6 +330,17 @@ def build_site(root: Path, out: Path) -> list[dict]: ) (cat_dir / "index.mdx").write_text(mt.serialize(_page_fm(fm), overview)) + functions_group.setdefault("items", []).append( + { + "label": fm["title"], + "collapsed": True, + "items": [ + {"label": "Overview", "link": f"/{slug_dir}/{category}/"}, + *links, + ], + } + ) + return sidebar diff --git a/docs/site/astro.config.mjs b/docs/site/astro.config.mjs index 440f98d..47546e5 100644 --- a/docs/site/astro.config.mjs +++ b/docs/site/astro.config.mjs @@ -16,6 +16,16 @@ export default defineConfig({ }, ], customCss: ['./src/styles/catppuccin.css'], + expressiveCode: { + // Shiki ships both Catppuccin flavours; Starlight picks by the + // reader's colour scheme, matching the palette in catppuccin.css. + themes: ['catppuccin-mocha', 'catppuccin-latte'], + styleOverrides: { + borderRadius: '0.4rem', + borderColor: 'var(--sl-color-gray-5)', + codeFontSize: '0.875rem', + }, + }, sidebar, }), ], diff --git a/docs/site/src/styles/catppuccin.css b/docs/site/src/styles/catppuccin.css index 7eaf590..8496ef4 100644 --- a/docs/site/src/styles/catppuccin.css +++ b/docs/site/src/styles/catppuccin.css @@ -1,5 +1,18 @@ /* Catppuccin Mocha (dark) / Latte (light) mapped onto Starlight tokens. */ :root { + --ctp-rosewater: #f5e0dc; + --ctp-pink: #f5c2e7; + --ctp-mauve: #cba6f7; + --ctp-red: #f38ba8; + --ctp-peach: #fab387; + --ctp-yellow: #f9e2af; + --ctp-green: #a6e3a1; + --ctp-teal: #94e2d5; + --ctp-sky: #89dceb; + --ctp-blue: #89b4fa; + --ctp-lavender: #b4befe; + --ctp-surface: #313244; + --sl-color-accent-low: #1e1e2e; --sl-color-accent: #89b4fa; --sl-color-accent-high: #b4befe; @@ -14,6 +27,19 @@ } :root[data-theme='light'] { + --ctp-rosewater: #dc8a78; + --ctp-pink: #ea76cb; + --ctp-mauve: #8839ef; + --ctp-red: #d20f39; + --ctp-peach: #fe640b; + --ctp-yellow: #df8e1d; + --ctp-green: #40a02b; + --ctp-teal: #179299; + --ctp-sky: #04a5e5; + --ctp-blue: #1e66f5; + --ctp-lavender: #7287fd; + --ctp-surface: #ccd0da; + --sl-color-accent-low: #dce0e8; --sl-color-accent: #1e66f5; --sl-color-accent-high: #7287fd; @@ -26,3 +52,97 @@ --sl-color-gray-6: #ccd0da; --sl-color-black: #eff1f5; } + +/* ── Headings ──────────────────────────────────────────────────────── */ +/* The manual is one long reference; tinting each level makes the + hierarchy scannable without relying on size alone. */ +.sl-markdown-content h1 { + color: var(--ctp-lavender); +} + +.sl-markdown-content h2 { + color: var(--ctp-mauve); + border-bottom: 1px solid var(--sl-color-gray-5); + padding-bottom: 0.2em; +} + +.sl-markdown-content h3 { + color: var(--ctp-blue); +} + +.sl-markdown-content h4 { + color: var(--ctp-teal); +} + +/* ── Inline code ───────────────────────────────────────────────────── */ +/* Function names, variables, and flags appear inline constantly; peach + separates them from prose the way the fenced blocks separate examples. */ +.sl-markdown-content :not(pre) > code { + color: var(--ctp-peach); + background: var(--ctp-surface); + border: 1px solid var(--sl-color-gray-5); + border-radius: 0.3em; + padding: 0.1em 0.35em; +} + +.sl-markdown-content a > code { + color: var(--ctp-sky); +} + +/* ── Links ─────────────────────────────────────────────────────────── */ +.sl-markdown-content a:not(:where(.not-content *)) { + color: var(--ctp-sky); + text-decoration-color: var(--sl-color-gray-4); +} + +.sl-markdown-content a:not(:where(.not-content *)):hover { + color: var(--ctp-teal); + text-decoration-color: currentColor; +} + +/* ── Cards ─────────────────────────────────────────────────────────── */ +/* Each function category is a grid of LinkCards; a hover accent makes the + grid feel navigable rather than like a wall of boxes. */ +.card { + border-color: var(--sl-color-gray-5); + transition: + border-color 150ms ease, + transform 150ms ease; +} + +.card:hover { + border-color: var(--ctp-mauve); + transform: translateY(-2px); +} + +.card .title { + color: var(--ctp-lavender); +} + +/* ── Asides ────────────────────────────────────────────────────────── */ +.starlight-aside--note { + --sl-color-asides-text-accent: var(--ctp-blue); +} + +.starlight-aside--tip { + --sl-color-asides-text-accent: var(--ctp-green); +} + +.starlight-aside--caution { + --sl-color-asides-text-accent: var(--ctp-yellow); +} + +.starlight-aside--danger { + --sl-color-asides-text-accent: var(--ctp-red); +} + +/* ── Site chrome ───────────────────────────────────────────────────── */ +.site-title { + color: var(--ctp-mauve); +} + +/* Table headers carry the accent so the many reference tables in the + manual read as structured data at a glance. */ +.sl-markdown-content th { + color: var(--ctp-yellow); +} diff --git a/docs/verify-manual.py b/docs/verify-manual.py index caa63a1..4ba56af 100644 --- a/docs/verify-manual.py +++ b/docs/verify-manual.py @@ -213,6 +213,86 @@ def test_site_build_produces_function_pages(): assert "title" in fm, f"{page.name} has no title" +def test_prettify_splits_an_entry_block(): + """A man-page-style entry becomes fenced code, prose, and a table.""" + import build_manual + + body = "\n".join( + [ + " Synopsis: rm [-e | args...]", + " Safe rm wrapper routing to trash:", + "", + " (no args) List current trash contents", + " -e/--empty Empty the trash", + "", + " Falls back to /usr/bin/rm when trash is unavailable.", + "", + " rm file.txt # moves to trash", + " rm -e # empty trash", + ] + ) + out = build_manual.prettify(body, "rm") + + assert "```fish\nrm [-e | args...]\n```" in out, "synopsis was not fenced as fish" + assert "```fish\nrm file.txt" in out, "examples were not fenced as fish" + assert out.count("```") == 4, f"expected exactly two fences, got:\n{out}" + assert "\nSafe rm wrapper routing to trash:" in out, "description stayed indented" + assert ( + "\n (no args) List current trash contents" in out + ), "option table lost its indentation" + assert ( + "\nFalls back to /usr/bin/rm when trash is unavailable." in out + ), "trailing prose stayed indented" + + +def test_prettify_leaves_reference_tables_alone(): + """Column-aligned blocks are data, not shell, and must not be fenced.""" + import build_manual + + table = " XDG_CONFIG_HOME ~/.config\n XDG_CACHE_HOME ~/.cache" + assert "```" not in build_manual.prettify(table), "a reference table got fenced" + + binds = " n / nv / neovim nvim\n e edit" + assert "```" not in build_manual.prettify(binds), "an abbreviation table got fenced" + + shell = " set -U __fish_user_dots_path /path/to/dots" + assert "```fish" in build_manual.prettify(shell), "a shell block was not fenced" + + +def test_prettify_is_site_only(): + """The SSOT keeps the indented form the man-page pipeline depends on.""" + import build_manual + + manual = Path(__file__).parent / "manual" + for path in manual.rglob("*.md"): + assert "```" not in path.read_text(), ( + f"{path.name} contains a fence: prettify must run at site-build " + "time, never be written back to the SSOT" + ) + + +def test_sidebar_has_no_duplicate_functions_entry(): + """The functions group must not also list itself as one of its children.""" + import build_manual + + docs = Path(__file__).parent + with tempfile.TemporaryDirectory() as d: + sidebar = build_manual.build_site(docs / "manual", Path(d)) + + groups = [e for e in sidebar if "items" in e] + assert len(groups) == 1, f"expected one sidebar group, got {len(groups)}" + group = groups[0] + labels = [item["label"] for item in group["items"]] + assert group["label"] not in labels[1:], ( + f"'{group['label']}' is repeated inside its own group: {labels}" + ) + assert labels[0] == "Overview", f"group should lead with Overview, got {labels[0]}" + assert not any( + "autogenerate" in item for item in group["items"] + ), "categories should be listed explicitly, not autogenerated from slugs" + assert len(labels) == 15, f"expected Overview + 14 categories, got {len(labels)}" + + TESTS = [v for k, v in sorted(globals().items()) if k.startswith("test_")] -- 2.52.0 From e684eb613459b913a595b00046653b862e5eb1ee Mon Sep 17 00:00:00 2001 From: rootiest Date: Sun, 26 Jul 2026 00:15:13 -0400 Subject: [PATCH 15/15] style(docs-site): use green as the primary accent instead of mauve Swaps the two usages: green now carries the site title, H2 headings, and the card hover accent; mauve moves to the tip aside it displaces. --- docs/site/src/styles/catppuccin.css | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/site/src/styles/catppuccin.css b/docs/site/src/styles/catppuccin.css index 8496ef4..18d1fa7 100644 --- a/docs/site/src/styles/catppuccin.css +++ b/docs/site/src/styles/catppuccin.css @@ -61,7 +61,7 @@ } .sl-markdown-content h2 { - color: var(--ctp-mauve); + color: var(--ctp-green); border-bottom: 1px solid var(--sl-color-gray-5); padding-bottom: 0.2em; } @@ -111,7 +111,7 @@ } .card:hover { - border-color: var(--ctp-mauve); + border-color: var(--ctp-green); transform: translateY(-2px); } @@ -125,7 +125,7 @@ } .starlight-aside--tip { - --sl-color-asides-text-accent: var(--ctp-green); + --sl-color-asides-text-accent: var(--ctp-mauve); } .starlight-aside--caution { @@ -138,7 +138,7 @@ /* ── Site chrome ───────────────────────────────────────────────────── */ .site-title { - color: var(--ctp-mauve); + color: var(--ctp-green); } /* Table headers carry the accent so the many reference tables in the -- 2.52.0