Compare commits

..
76 Commits
Author SHA1 Message Date
alexion d342370b89 feat(nixos): deploy Gitea on Pikachu 2026-10-22 19:51:32 -04:00
alexion c370d635e5 feat(emulation): declare RetroArch configuration 2026-10-22 13:51:33 -04:00
alexion 8756bc087f fix(adguard): disable DNS request rate limit
The private resolver grouped clients by IPv4 /24 and silently dropped requests above 20 queries per second. Disable the public-server protection so internal DNS bursts complete.
2026-10-22 13:34:58 -04:00
alexion bb22a90053 feat(ssh): add Steam Machine target 2026-10-22 11:00:46 -04:00
alexion 5cf7109eaf docs: update homelab plans 2026-10-21 20:35:37 -04:00
alexion 4baafb7094 feat(discord): configure official client 2026-10-21 20:32:31 -04:00
alexion 0166547091 feat(steam): configure Quest VR streaming 2026-10-21 19:27:57 -04:00
alexion 1a2a4bd2bd feat(nixos): migrate AdGuard to Pikachu 2026-10-21 18:51:29 -04:00
alexion 94eb132962 fix(shell): reuse sudo session during deployment 2026-10-21 17:03:42 -04:00
alexion 8e01e1621b fix(nixos): add RomM Homepage entry 2026-10-21 14:33:36 -04:00
alexion b4e74fc5b2 feat(zeus): add RetroArch 2026-10-21 12:05:28 -04:00
alexion bbac95cac0 feat(romm): enable Playmatch metadata 2026-10-21 00:21:07 -04:00
alexion e5bacc53be feat(romm): enable Hasheous metadata 2026-10-21 00:19:48 -04:00
alexion 5f52a78efa fix(romm): run scan queue workers 2026-10-21 00:15:47 -04:00
alexion dc210d4985 fix(romm): remove upload size limit 2026-10-21 00:07:59 -04:00
alexion 2237c3eea3 fix(reverse-proxy): forward WebSocket upgrades 2026-10-21 00:07:01 -04:00
alexion 771a0df831 feat(romm): package version 5.4.0 2026-10-21 00:01:31 -04:00
alexion cfa01fb550 fix(grill): clarify decision planning 2026-10-20 20:35:35 -04:00
alexion 7186d6a3a7 refactor(nixos): scope agent guidance 2026-10-20 04:40:14 -04:00
alexion c836396cbe docs(tasks): close RomM guest task 2026-10-19 23:36:01 -04:00
alexion 3493519085 feat(nixos): deploy RomM guest 2026-10-19 23:35:07 -04:00
alexion f160fd15a2 fix(neogaia): restore Caps Escape swap 2026-10-19 20:41:12 -04:00
alexion f1a93199c7 docs: plan RomM migration 2026-10-19 20:04:50 -04:00
alexion 591144df33 docs(tasks): close NixOS refactor task 2026-10-19 16:45:48 -04:00
alexion d7760ef84d docs(tasks): track gitea-axi packaging migration 2026-10-19 16:45:48 -04:00
alexion 042238476a feat(pi): add tldr prompt command 2026-10-19 16:04:30 -04:00
alexion e41b8e3eb4 docs: capture agent workflow decisions 2026-10-19 02:41:41 -04:00
alexion 63017f8e33 feat(skills): add grill skill 2026-10-19 02:32:34 -04:00
alexion 52f31fd44d docs(tasks): add Gitea Axi tasks 2026-10-18 15:44:55 -04:00
alexion 898a6df333 fix(skills): clarify skill guidance 2026-10-18 15:40:23 -04:00
alexion 5a5543633c fix(agents): preserve review-only requests 2026-10-18 15:05:55 -04:00
alexion 9c501a79ad feat(skills): add retrospective skill 2026-10-18 14:51:59 -04:00
alexion 30e5b1e677 docs: add project task notes 2026-10-18 01:16:20 -04:00
alexion 45a840002f refactor(skills): remove redundant skills 2026-10-17 22:04:31 -04:00
alexion a9db1f8b7c feat(skills): add agent writing guide 2026-10-17 22:04:31 -04:00
alexion dcc4efcc75 fix(rofi): migrate Home Manager options 2026-10-15 18:16:47 -04:00
alexion a23a317335 build(nix): update flake inputs 2026-10-15 18:16:47 -04:00
alexion 6e545c0a15 build(pi): integrate vendored Pi 1.3.0 2026-10-15 18:05:57 -04:00
alexion 6081e3e325 chore(vendor): import pi 1.3.0
Imported as a linear vendor commit so forge rebases do not replay the upstream root tree.

git-subtree-dir: third_party/pi

git-subtree-split: 71023aec1546d6d677a65669c5665c0927ce0dd0
2026-10-15 17:58:48 -04:00
alexion 719370c8f7 refactor(bazel): inline the primary user 2026-10-15 14:23:18 -04:00
alexion 2b4e66a75c fix(palworld): configure the RCON port 2026-10-15 14:18:27 -04:00
alexion c44769ff70 refactor(steamcmd): constrain service names 2026-10-15 14:13:07 -04:00
alexion 1397576538 refactor(reverse-proxy): simplify virtual host generation 2026-10-15 13:57:45 -04:00
alexion 5fbe1850e0 docs(tasks): organize task areas 2026-10-14 18:18:18 -04:00
alexion 57bb21af1a feat(vault): add task workflow 2026-10-14 01:24:22 -04:00
alexion ffc40e547b feat(skills): add Conventional Commits skill 2026-10-13 22:49:44 -04:00
alexion 55f61f71d8 refactor(natu): remove custom Nix linter 2026-10-13 21:59:41 -04:00
alexion 08563c6769 refactor(nixos): remove unused direnv module 2026-10-13 21:50:37 -04:00
alexion 8462b3a5a8 refactor(copyparty): separate deployment and service policy
Move Copyparty rendering into shared dotfiles utilities, keep guest wiring focused on host/container plumbing, and let the service module derive effective volume policy.
2026-10-13 20:33:25 -04:00
alexion d0872e7d8c fix(homepage): skip empty ordered sections 2026-10-12 11:50:27 -04:00
alexion 9be9ad7675 refactor(actualbudget): remove unused service 2026-10-12 11:40:05 -04:00
alexion 5ee328cdf8 refactor(flake): centralize custom packages 2026-10-12 11:34:18 -04:00
alexion 6532a822cd feat(userdirs): configure preferred directories 2026-10-11 22:54:11 -04:00
alexion 20a3990979 refactor(theming): simplify stylix module 2026-10-11 22:43:35 -04:00
alexion b7ab518f58 refactor(screenshot): simplify capture bindings 2026-10-11 22:40:44 -04:00
alexion 3f1e34ef95 refactor(recording): signal status updates 2026-10-11 22:37:30 -04:00
alexion d0abfc1625 refactor(osd): move volume bindings to audio 2026-10-11 22:33:32 -04:00
alexion 031090e4ea fix(waybar): use Lua dispatch build 2026-10-11 22:12:17 -04:00
alexion 2edad6c5df refactor(clipboard): simplify picker wiring 2026-10-11 21:36:54 -04:00
alexion 1d5acc09c6 refactor(audio): simplify media controls 2026-10-11 21:30:21 -04:00
alexion ee29e53f7c refactor(waybar): register owned modules 2026-10-11 21:07:35 -04:00
alexion 3c9d0ec886 refactor(nix): share glyph decoding helper 2026-10-11 21:07:35 -04:00
alexion f0c5544b10 refactor(waybar): register workspace window icons 2026-10-11 18:23:41 -04:00
alexion 4dd0a5a4f5 feat(rofi): increase launcher contrast 2026-10-11 17:49:05 -04:00
alexion a4a795f7ee refactor(mako): use executable helper for history 2026-10-11 17:40:56 -04:00
alexion ecdf877308 refactor(login): use configured uwsm executable 2026-10-11 17:39:37 -04:00
alexion d1face10ec refactor(nix): apply executable helper rules 2026-10-11 17:38:15 -04:00
alexion 337d9a2014 docs(nix-style): add package command rules 2026-10-11 17:38:15 -04:00
alexion f059068873 refactor(hyprlock): inline command paths 2026-10-11 17:25:18 -04:00
alexion 7662c04cda fix(hypridle): use Lua dpms dispatcher 2026-10-11 17:22:05 -04:00
alexion 33128fc3c7 feat(hyprland): migrate desktop utility bindings 2026-10-11 16:58:27 -04:00
alexion 68415ad47e fix(hyprland): place Zeus primary monitor at origin 2026-10-11 16:56:03 -04:00
alexion 6b7201e6fa feat(hyprland): migrate session feature bindings 2026-10-11 16:52:29 -04:00
alexion 4360f4863b feat(hyprland): migrate hardware key bindings 2026-10-11 16:40:07 -04:00
alexion 370cab8f83 feat(hyprland): render session env registry 2026-10-11 16:34:52 -04:00
alexion e74a08b853 feat(dotfiles): add session env registry 2026-10-11 16:30:00 -04:00
2985 changed files with 245979 additions and 488973 deletions

No files matched your search

-10
View File
@@ -17,15 +17,6 @@ If the target includes multiple matching file types, use all matching skills.
If the target is a diff, choose skills from the changed files. If the target is a diff, choose skills from the changed files.
Do not use a style skill when no reviewed file matches it. Do not use a style skill when no reviewed file matches it.
For every reviewed `*.nix` file, run:
```bash
bazel run //src/natu:natu -- <reviewed-nix-paths>
```
Pass every reviewed Nix path to Natu.
Report every Natu diagnostic as an actionable finding.
Report only actionable findings. Report only actionable findings.
Order findings by severity. Order findings by severity.
Do not report preferences unless a loaded rule states them. Do not report preferences unless a loaded rule states them.
@@ -45,7 +36,6 @@ Keep the code excerpt to one to three lines when possible.
Use a longer excerpt only when the violation needs surrounding context. Use a longer excerpt only when the violation needs surrounding context.
Use `...` to omit unrelated lines from a multi-line excerpt. Use `...` to omit unrelated lines from a multi-line excerpt.
Use a style-skill rule citation in the form `skill::rule-file:line`. Use a style-skill rule citation in the form `skill::rule-file:line`.
Cite Natu diagnostics as `natu::<rule-id>`.
Make the fix direct. Make the fix direct.
Do not include alternatives when one fix best follows the cited rule. Do not include alternatives when one fix best follows the cited rule.
+8
View File
@@ -0,0 +1,8 @@
---
description: Summarize an agent response
argument-hint: "[source request]"
---
Summarize `${ARGUMENTS:-the preceding agent response}`.
Keep the summary compact.
Use no fixed format.
+1
View File
@@ -0,0 +1 @@
../../src/skills/agent-writing-guide
+1
View File
@@ -0,0 +1 @@
../../src/skills/conventional-commits
-1
View File
@@ -1 +0,0 @@
../../src/skills/craft-skill
+1
View File
@@ -0,0 +1 @@
../../src/skills/retrospect
-1
View File
@@ -1 +0,0 @@
../../src/skills/to-document
+8 -20
View File
@@ -3,7 +3,6 @@
## Commit convention ## Commit convention
- Use Conventional Commits for all commit messages. - Use Conventional Commits for all commit messages.
Before writing a commit message, read `docs/conventional-commits.md`.
- Keep commit messages about the Git history, not the forge workflow. - Keep commit messages about the Git history, not the forge workflow.
Include external references only when they are stable context for the change. Include external references only when they are stable context for the change.
- When writing commit messages, NEVER auto-add your agent name as co-author. - When writing commit messages, NEVER auto-add your agent name as co-author.
@@ -49,6 +48,8 @@
- NEVER ask the user a question using the `AskUserQuestion` tool. - NEVER ask the user a question using the `AskUserQuestion` tool.
Ask in plain prose, in your own message, instead, with no exceptions. Ask in plain prose, in your own message, instead, with no exceptions.
This overrides any default instruction to use it. This overrides any default instruction to use it.
- For review requests, inspect the requested material and report findings.
Edit files after the operator accepts a proposed change.
- Never manually modify `CHANGELOG.md` files or files marked as auto-generated. - Never manually modify `CHANGELOG.md` files or files marked as auto-generated.
Detect auto-generated files with a layered check. Detect auto-generated files with a layered check.
Trust an explicit in-file marker first, for example `AUTO-GENERATED, DO NOT EDIT`. Trust an explicit in-file marker first, for example `AUTO-GENERATED, DO NOT EDIT`.
@@ -68,20 +69,6 @@
after applying an accepted change. after applying an accepted change.
If the workflow is paused, say that plainly instead of using a dangling transition like "continuing" or "next". If the workflow is paused, say that plainly instead of using a dangling transition like "continuing" or "next".
## Corrections
- When you discover that your belief about a project fact or convention was wrong, record the correction.
Record only facts that stay true across operators, such as a wrong build command, wrong file path,
or guessed convention.
Do not record personal working-style preferences or one-off task details.
- Record the correction in the nearest project `AGENTS.md`.
Use a dedicated `## Gotchas` section.
Create that section when the file lacks one.
- If no project `AGENTS.md` exists, ask before creating one.
Append the correction immediately without asking when a project `AGENTS.md` exists.
Briefly mention the edit in your response.
If an existing entry is wrong or stale, correct or remove it the same way.
## Gotchas ## Gotchas
- When materializing an external specification, standard, or project-maintained convention, use the - When materializing an external specification, standard, or project-maintained convention, use the
@@ -101,17 +88,12 @@
- Ariadne Rust tests are declared in Bazel `BUILD` files; do not add `[[test]]` entries to - Ariadne Rust tests are declared in Bazel `BUILD` files; do not add `[[test]]` entries to
`src/ariadne/Cargo.toml` unless explicitly requested. `src/ariadne/Cargo.toml` unless explicitly requested.
- In this monorepo, "dotfiles" refers to the dotfiles/NixOS configuration under `src/dotfiles/` and `configs/nixos/`. - In this monorepo, "dotfiles" refers to the dotfiles/NixOS configuration under `src/dotfiles/` and `configs/nixos/`.
- The flake does not currently define `formatter.x86_64-linux`.
Do not use `nix fmt` as a validation command until a formatter is added.
- The `fix` app passes its current directory to Deadnix. - The `fix` app passes its current directory to Deadnix.
Run `nix run .#fix` from the repository root so path exclusions match. Run `nix run .#fix` from the repository root so path exclusions match.
- During the Nix refactor, address each issue that comes up by adding either a Natu rule or a new Nix style rule.
- Git pathspec searches started in a subdirectory default to that subtree. - Git pathspec searches started in a subdirectory default to that subtree.
Use `git -C <repository-root>` or top-anchored pathspecs for repository-wide history searches. Use `git -C <repository-root>` or top-anchored pathspecs for repository-wide history searches.
- A `**/*.nix` Git pathspec does not include Nix files directly in its starting directory. - A `**/*.nix` Git pathspec does not include Nix files directly in its starting directory.
Include both `*.nix` and `**/*.nix`, or use a recursive `*.nix` pathspec, when linting every Nix file. Include both `*.nix` and `**/*.nix`, or use a recursive `*.nix` pathspec, when linting every Nix file.
- Nix `let` bindings are recursive; their source order does not determine binding availability.
Treat Natu `let_order` as a readability rule, not an evaluation dependency.
- Ariadne extraction must preserve the game-root season prefix for archived source. - Ariadne extraction must preserve the game-root season prefix for archived source.
Different game installs can contain compiled scripts with the same internal path. Different game installs can contain compiled scripts with the same internal path.
- Clew owns Ren'Py extraction, preparation, and compiled-script AST export. Ariadne owns analysis over Clew-produced data. - Clew owns Ren'Py extraction, preparation, and compiled-script AST export. Ariadne owns analysis over Clew-produced data.
@@ -122,7 +104,13 @@
- OMP does not discover project skills from `.pi/skills`. - OMP does not discover project skills from `.pi/skills`.
Put skills shared by Pi and OMP under `.agents/skills`, or configure OMP's `skills.customDirectories`. Put skills shared by Pi and OMP under `.agents/skills`, or configure OMP's `skills.customDirectories`.
- Pi is vendored under `third_party/pi` as a linear vendor import. - Pi is vendored under `third_party/pi` as a linear vendor import.
`pkgs.alexion.pi-coding-agent` packages that source and does not use Nixpkgs Pi.
Do not use `git subtree add` or `git subtree pull` for Pi PR branches. Do not use `git subtree add` or `git subtree pull` for Pi PR branches.
Gitea rebases the synthetic upstream root commit without the `third_party/pi` prefix. Gitea rebases the synthetic upstream root commit without the `third_party/pi` prefix.
Preserve `git-subtree-dir` and `git-subtree-split` trailers on Pi vendor commits. Preserve `git-subtree-dir` and `git-subtree-split` trailers on Pi vendor commits.
- The default Pi model for NixOS user configuration is set in `configs/nixos/modules/shell/pi/default.nix`, not in vendored Pi source. - The default Pi model for NixOS user configuration is set in `configs/nixos/modules/shell/pi/default.nix`, not in vendored Pi source.
- The `monorepo` and `status` libraries do not have `README.md` files.
- Check root and `src/skills/.pi/skills/` for enabled symlinks before removing a monorepo skill.
- Ariadne Rust source files live directly under `src/ariadne/`. The binary entry point is `ariadne_main.rs.
- Bazel build-style rules live under `src/skills/style/build/rules/`, not `src/skills/style/rules/`.
- Bazel passes arguments after `--` to the executed binary verbatim. A scaffold can define `//path` as a destination-path syntax.
Generated
+2 -152
View File
@@ -2,15 +2,6 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 4 version = 4
[[package]]
name = "aho-corasick"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "anstream" name = "anstream"
version = "1.0.0" version = "1.0.0"
@@ -71,12 +62,6 @@ dependencies = [
"serde_json", "serde_json",
] ]
[[package]]
name = "autocfg"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.6.7" version = "4.6.7"
@@ -108,7 +93,7 @@ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 3.0.6", "syn",
] ]
[[package]] [[package]]
@@ -123,41 +108,6 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
[[package]]
name = "countme"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636"
[[package]]
name = "googletest"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6b5e2f2b556b7b90297a5a35c8267dd43a537923d2b329beefdba2b4ec19d94"
dependencies = [
"googletest_macro",
"num-traits",
"regex",
"rustversion",
]
[[package]]
name = "googletest_macro"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ae6abc96141edd26bf5aeec0f119c129c44de3ced09e5073711a02cb74725d0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.119",
]
[[package]]
name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
[[package]] [[package]]
name = "heck" name = "heck"
version = "0.5.0" version = "0.5.0"
@@ -190,27 +140,6 @@ checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
name = "monorepo" name = "monorepo"
version = "0.1.0" version = "0.1.0"
[[package]]
name = "natu"
version = "0.1.0"
dependencies = [
"clap",
"googletest",
"monorepo",
"rnix",
"rowan",
"status",
]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "once_cell_polyfill" name = "once_cell_polyfill"
version = "1.70.2" version = "1.70.2"
@@ -235,68 +164,6 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "regex"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
[[package]]
name = "rnix"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c163bd17372eecdf10d351c34584b7de7c1a33be4e92a32f3fb3f5a7fe3f579b"
dependencies = [
"rowan",
]
[[package]]
name = "rowan"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "417a3a9f582e349834051b8a10c8d71ca88da4211e4093528e36b9845f6b5f21"
dependencies = [
"countme",
"hashbrown",
"rustc-hash",
"text-size",
]
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustversion"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.229" version = "1.0.229"
@@ -324,7 +191,7 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 3.0.6", "syn",
] ]
[[package]] [[package]]
@@ -350,17 +217,6 @@ version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]] [[package]]
name = "syn" name = "syn"
version = "3.0.6" version = "3.0.6"
@@ -372,12 +228,6 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "text-size"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.26" version = "1.0.26"
-4
View File
@@ -4,16 +4,12 @@ members = [
"src/machoke", "src/machoke",
"src/monorepo", "src/monorepo",
"src/status", "src/status",
"src/natu",
] ]
resolver = "3" resolver = "3"
[workspace.dependencies] [workspace.dependencies]
clap = "4" clap = "4"
googletest = "0.14"
monorepo = { path = "src/monorepo" } monorepo = { path = "src/monorepo" }
rnix = "=0.14.0"
rowan = "0.16"
serde = "1.0" serde = "1.0"
serde_json = "1.0" serde_json = "1.0"
status = { path = "src/status" } status = { path = "src/status" }
-67
View File
@@ -1,67 +0,0 @@
# NixOS configuration instructions
## Desktop
- TODO: Verify this path after the NixOS configuration is migrated.
When adding a graphical application, add a `window-rewrite` icon mapping in `modules/desktop/session/waybar.nix`.
The workspace indicator uses this mapping to show an application icon instead of the generic default glyph.
Match the mapping on the window class.
Run `hyprctl clients -j | jq -r '.[].class' | sort -u` to list classes in the running session.
- TODO: Verify this path after the NixOS configuration is migrated.
Set Hyprland session environment variables in `modules/desktop/session/hyprland/default.nix` with `env = KEY,VALUE`.
`home.sessionVariables` do **not** reach the Hyprland session because UWSM does not source `hm-session-vars.sh`.
Source cursor values from `config.stylix.cursor`.
Set `XCURSOR_*` and `HYPRCURSOR_*` to the same theme for Bibata.
## Firefox
- Manage Firefox search engines through `programs.firefox.search` with `force = true`.
Hide built-in engines with `<engine>.metaData.hidden = true` because omission does not remove them.
Use current engine ids, such as `default = "ddg"` instead of `"DuckDuckGo"`.
Decode the built `search.json.mozlz4` with `mozlz4a -d <search.json.mozlz4>` to check the result.
- Avoid Home Manager Firefox extension settings unless the whole profile can use the legacy extension-storage backend.
Any non-empty `profiles.<name>.extensions.settings.<id>.settings` sets `extensions.webextensions.ExtensionStorageIDB.enabled = false` for the whole profile.
## Neovim
- Nixvim's flake input follows the root nixpkgs source, but its Home Manager module does not reuse the host's `pkgs` instance.
Keep `programs.nixvim.nixpkgs.useGlobalPackages = true`.
That setting makes Nixvim use the shared package set without warning that its source default changed.
## AI tooling
- Use produced literals for Herdr key names that include shifted punctuation.
For example, use `prefix+<` instead of `prefix+shift+comma`.
- Put monorepo Pi extension sources in `.pi/extensions/`.
Pi discovers them from subdirectories through the local ancestor-resource patch.
- Treat Home Manager-managed Pi settings as generated output.
Do not edit them except for throwaway development or local experiments.
Promote finished settings into the NixOS configuration before treating them as deployed.
## Gotchas
- `configs/nixos/registry/stable-uid.nix` receives library functions through `lib`.
Qualify its library calls with `lib.`.
- Guest modules are host-agnostic wiring, while host files own deployment-specific service configuration such as served volumes and host paths.
For example, `guests/copyparty.nix` should expose options and translate them into guest mounts/service settings, while `hosts/pikachu/default.nix` chooses `/inbox`, `/media`, and their backing paths.
Guest addresses and routes are host-level configuration because a guest module can be used on multiple hosts.
- `sops.secrets.<name>.owner` must name a user known on the decrypting host.
Do not set the owner to a guest-only service user unless the host also declares that user.
Use a host-visible owner plus a shared group mode when the guest service can read the decrypted secret file through its group.
- A read-only guest bind mount cannot contain nested writable bind mounts unless their mount-point
directories already exist inside the read-only source.
For aggregate Copyparty volumes such as `/srv` with nested `/srv/inbox`, keep the guest bind mount
writable and enforce read-only behavior through Copyparty access plus service `ReadWritePaths`.
- `deploy-to` builds from the source checkout, records the imported closure as the target system profile,
and activates it. Do not rely on a target-local monorepo checkout for remote deployment.
- On Pikachu, `nix copy --to ssh://pikachu` accepted a small `nix store add-file` probe,
but rejected locally built system paths that lacked trusted signatures.
Use a sudo `nix-store --import` path for unsigned deploy closures.
- Public DNS entries are not managed through the NixOS configuration.
Do not describe NixOS route choices as public-DNS management.
- Do not hand-author `hardware-configuration.nix` for a host that has not been generated on that machine.
Generate it on the target system or live ISO, then stage it before evaluating the flake.
- Configure the Chaotic Nyx cache only on hosts that select `linuxPackages_cachyos` (currently Neogaia
and Zeus), not in the generic host module.
- Module-relative paths resolve from the module file. Update them when moving a module into a subdirectory.
- On Pikachu, `uptime` does not support `-s`. Use `who -b` to report the boot time.
+1 -1
View File
@@ -102,7 +102,7 @@ Confirm you have connectivity (`ping -c1 github.com`) before continuing.
Clone the monorepo onto the live ISO and work from that local checkout: Clone the monorepo onto the live ISO and work from that local checkout:
```console ```console
$ git clone ssh://gitea@git.alexion.dev:2022/alexion/dev.git $ git clone ssh://gitea@git.alexion.dev/alexion/dev.git
$ cd dev $ cd dev
``` ```
-51
View File
@@ -1,51 +0,0 @@
{
config,
lib,
...
}:
let
cfg = config.guests.actualbudget; # NOLINT(let_order)
dataDir = "/data";
in
{
options.guests.actualbudget = {
dataPath = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "/srv/actualbudget";
description = "Host path bind-mounted as Actual Budget's data directory.";
};
};
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = cfg.dataPath != null;
message = "guests.actualbudget.dataPath must point at the host directory that stores Actual Budget data.";
}
];
registry.homepage.${config.networking.hostName}.actualbudget = {
tab = "Apps";
section = "Other";
name = "Actual Budget";
description = "Finance";
icon = "actual-budget.png";
};
guests.actualbudget = {
interior = {
modules.services.actualbudget = {
enable = true;
inherit dataDir;
};
};
mounts.${dataDir}.directory = cfg.dataPath;
limits = {
memory = lib.mkDefault "2G";
cpu = lib.mkDefault "200%";
tasksMax = lib.mkDefault 512;
};
};
};
}
+51
View File
@@ -0,0 +1,51 @@
{
config,
lib,
registry,
...
}:
let
cfg = config.guests.adguard;
in
{
options.guests.adguard.adminPasswordHash = lib.mkOption {
type = lib.types.str;
description = "Bcrypt verifier for the AdGuard Home administrator password.";
};
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = cfg.address != null;
message = "guests.adguard.address must identify the AdGuard Home guest.";
}
];
registry.homepage.${config.networking.hostName}.adguard = {
tab = "System";
section = "Network";
name = "AdGuard Home";
description = "Internal DNS";
icon = "adguard-home.svg";
href = "http://${cfg.address}";
};
guests.adguard = {
interior = {
modules.services.adguardhome = {
enable = true;
inherit (cfg) adminPasswordHash;
reverseProxyAddress = registry.address.${config.networking.hostName}."reverse-proxy";
};
services.resolved.settings.Resolve.DNSStubListener = false;
};
limits = {
memory = lib.mkDefault "256M";
cpu = lib.mkDefault "100%";
tasksMax = lib.mkDefault 128;
};
};
};
}
+37 -47
View File
@@ -4,9 +4,32 @@
... ...
}: }:
let let
cfg = config.guests.copyparty; # NOLINT(let_order) cfg = config.guests.copyparty;
in
{
options.guests.copyparty = {
passwordSecret = lib.mkOption {
type = lib.types.str;
default = "services/copyparty/users/${config.user.name}/password";
description = "SOPS secret name that contains the Copyparty account password.";
};
volumeType = lib.types.submodule { statePath = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "/srv/copyparty";
description = "Host path bind-mounted as Copyparty's state directory.";
};
reverseProxy.trustedSources = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = "IP ranges that may supply Copyparty's forwarded client IP header.";
};
volumes = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule {
options = { options = {
hostPath = lib.mkOption { hostPath = lib.mkOption {
type = lib.types.str; type = lib.types.str;
@@ -31,48 +54,13 @@ let
}; };
flags = lib.mkOption { flags = lib.mkOption {
type = lib.types.listOf lib.types.str; type = lib.types.attrs;
default = [ ]; default = { };
description = "Copyparty volume flags."; description = "Copyparty volume flags.";
}; };
}; };
}; }
in );
{
options.guests.copyparty = {
accountName = lib.mkOption {
type = lib.types.str;
default = "alexion";
description = "Copyparty account name configured for password authentication.";
};
passwordSecret = lib.mkOption {
type = lib.types.str;
default = "services/copyparty/users/alexion/password";
description = "SOPS secret name containing the Copyparty account password.";
};
stateDir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/copyparty";
description = "Guest path where Copyparty stores service state.";
};
statePath = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "/srv/copyparty";
description = "Host path bind-mounted as Copyparty's state directory.";
};
reverseProxy.trustedSources = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = "IP ranges that may supply Copyparty's forwarded client IP header.";
};
volumes = lib.mkOption {
type = lib.types.attrsOf volumeType;
default = { }; default = { };
description = "Copyparty volumes keyed by their URL path."; description = "Copyparty volumes keyed by their URL path.";
}; };
@@ -102,24 +90,26 @@ in
guests.copyparty = { guests.copyparty = {
interior.modules.services.copyparty = { interior.modules.services.copyparty = {
enable = true; enable = true;
inherit (cfg) accountName stateDir;
passwordFile = "/run/secrets/${cfg.passwordSecret}"; passwordFile = "/run/secrets/${cfg.passwordSecret}";
reverseProxy = { reverseProxy = {
enable = cfg.reverseProxy.enable; enable = cfg.reverseProxy.enable;
inherit (cfg.reverseProxy) trustedSources; inherit (cfg.reverseProxy) trustedSources;
}; };
volumes = lib.mapAttrs (_urlPath: volume: { volumes = lib.mapAttrs (
_urlPath: volume:
{
inherit (volume) inherit (volume)
path path
access
flags
readOnly readOnly
; ;
}) cfg.volumes; }
// lib.optionalAttrs (volume.access != { }) { inherit (volume) access; }
// lib.optionalAttrs (volume.flags != { }) { inherit (volume) flags; }
) cfg.volumes;
}; };
mounts = { mounts = {
${cfg.stateDir} = { "/var/lib/copyparty" = {
directory = cfg.statePath; directory = cfg.statePath;
owner = config.registry."stable-uid".${config.networking.hostName}.copyparty; owner = config.registry."stable-uid".${config.networking.hostName}.copyparty;
group = "storage"; group = "storage";
+48
View File
@@ -0,0 +1,48 @@
{
config,
lib,
registry,
...
}:
let
cfg = config.guests.gitea;
in
{
options.guests.gitea.dataPath = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "/srv/gitea";
description = "Host path mounted as Gitea's state directory.";
};
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = cfg.dataPath != null;
message = "guests.gitea.dataPath must point at the host directory that stores Gitea state.";
}
];
registry.homepage.${config.networking.hostName}.gitea = {
tab = "Apps";
section = "Other";
name = "Gitea";
description = "Git forge";
icon = "gitea.png";
};
guests.gitea = {
interior.modules.services.gitea = {
enable = true;
reverseProxyAddress = registry.address.${config.networking.hostName}."reverse-proxy";
};
mounts."/var/lib/gitea" = {
directory = cfg.dataPath;
owner = config.registry."stable-uid".${config.networking.hostName}.gitea;
group = "storage";
mode = "2770";
};
};
};
}
+1 -1
View File
@@ -4,7 +4,7 @@
... ...
}: }:
let let
cfg = config.guests.homepage; # NOLINT(let_order) cfg = config.guests.homepage;
environmentFile = "/run/secrets/homepage.env"; environmentFile = "/run/secrets/homepage.env";
in in
{ {
+1 -1
View File
@@ -4,7 +4,7 @@
... ...
}: }:
let let
cfg = config.guests.palworld; # NOLINT(let_order) cfg = config.guests.palworld;
steamDir = "/data/steamcmd"; steamDir = "/data/steamcmd";
installDir = "/data/server"; installDir = "/data/server";
stateDir = "/data/state"; stateDir = "/data/state";
+4 -16
View File
@@ -1,11 +1,9 @@
{ {
config, config,
lib, lib,
registry,
... ...
}: }:
let
giteaSshBackend = "10.23.20.45:2022";
in
{ {
config = lib.mkIf config.guests.reverse-proxy.enable { config = lib.mkIf config.guests.reverse-proxy.enable {
guests.reverse-proxy = { guests.reverse-proxy = {
@@ -13,16 +11,6 @@ in
modules.services.reverse-proxy.enable = true; modules.services.reverse-proxy.enable = true;
services.nginx.virtualHosts = { services.nginx.virtualHosts = {
"games.alexion.dev" = {
forceSSL = true;
enableACME = true;
locations."/".proxyPass = "http://10.23.20.32";
};
"git.alexion.dev" = {
forceSSL = true;
enableACME = true;
locations."/".proxyPass = "http://10.23.20.32";
};
"photos.alexion.dev" = { "photos.alexion.dev" = {
forceSSL = true; forceSSL = true;
enableACME = true; enableACME = true;
@@ -50,12 +38,12 @@ in
}; };
}; };
networking.firewall.allowedTCPPorts = [ 2022 ]; networking.firewall.allowedTCPPorts = [ 22 ];
services.nginx.streamConfig = '' services.nginx.streamConfig = ''
server { server {
listen 2022; listen 22;
proxy_pass ${giteaSshBackend}; proxy_pass ${registry.address.${config.networking.hostName}.gitea}:2222;
} }
''; '';
}; };
+193
View File
@@ -0,0 +1,193 @@
{
config,
lib,
...
}:
let
cfg = config.guests.romm;
rommUid = config.registry."stable-uid".${config.networking.hostName}.romm;
redisUid = config.registry."stable-uid".${config.networking.hostName}."redis-romm";
in
{
options.guests.romm = {
dataPath = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "/srv/romm";
description = "Host path mounted as RomM application data.";
};
postgresqlPath = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "/srv/romm/postgresql";
description = "Host path mounted as RomM's PostgreSQL data.";
};
redisPath = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "/srv/romm/redis";
description = "Host path mounted as RomM's Redis data.";
};
romsPath = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "/srv/roms";
description = "Host path mounted as RomM's ROM library.";
};
biosPath = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "/srv/bios";
description = "Host path mounted as RomM's BIOS library.";
};
usersPath = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "/srv/romm/users";
description = "Host path mounted as RomM's user assets.";
};
};
config = lib.mkIf cfg.enable {
assertions =
map
(path: {
assertion = path.value != null;
message = "guests.romm.${path.name} must point at the host directory that stores ${path.description}.";
})
[
{
name = "dataPath";
value = cfg.dataPath;
description = "RomM application data";
}
{
name = "postgresqlPath";
value = cfg.postgresqlPath;
description = "RomM PostgreSQL data";
}
{
name = "redisPath";
value = cfg.redisPath;
description = "RomM Redis data";
}
{
name = "romsPath";
value = cfg.romsPath;
description = "RomM's ROM library";
}
{
name = "biosPath";
value = cfg.biosPath;
description = "RomM's BIOS library";
}
{
name = "usersPath";
value = cfg.usersPath;
description = "RomM's user assets";
}
];
registry.homepage.${config.networking.hostName}.romm = {
tab = "Apps";
section = "Media";
name = "RomM";
description = "Games";
icon = "romm.png";
};
guests.romm = {
interior = {
modules.services.romm.enable = true;
services.romm.nginx.virtualHost = cfg.reverseProxy.route.domain;
};
mounts = {
"/var/lib/romm" = {
directory = cfg.dataPath;
owner = rommUid;
group = "storage";
mode = "2770";
};
"/var/lib/postgresql" = {
directory = cfg.postgresqlPath;
owner = config.ids.uids.postgres;
group = "storage";
mode = "0700";
};
"/var/lib/redis-romm" = {
directory = cfg.redisPath;
owner = redisUid;
group = "storage";
mode = "0700";
};
"/var/lib/romm/library/roms" = {
directory = cfg.romsPath;
owner = rommUid;
group = "storage";
mode = "2770";
};
"/var/lib/romm/library/bios" = {
directory = cfg.biosPath;
owner = rommUid;
group = "storage";
mode = "2770";
};
"/var/lib/romm/assets/users" = {
directory = cfg.usersPath;
owner = rommUid;
group = "storage";
mode = "2770";
};
"/run/secrets/romm.env" = {
file = config.sops.templates."romm.env".path;
readOnly = true;
};
};
limits = {
memory = lib.mkDefault "4G";
cpu = lib.mkDefault "200%";
tasksMax = lib.mkDefault 512;
};
};
sops.secrets =
lib.genAttrs
[
"services/romm/igdb/client-id"
"services/romm/igdb/client-secret"
"services/romm/retroachievements/api-key"
"services/romm/screenscraper/dev/id"
"services/romm/screenscraper/dev/password"
"services/romm/screenscraper/user"
"services/romm/screenscraper/password"
"services/romm/steamgriddb/api-key"
]
(_: {
sopsFile = ../secrets + "/${config.networking.hostName}.yaml";
});
sops.templates."romm.env" = {
owner = "root";
group = "storage";
mode = "0440";
content = ''
IGDB_CLIENT_ID=${config.sops.placeholder."services/romm/igdb/client-id"}
IGDB_CLIENT_SECRET=${config.sops.placeholder."services/romm/igdb/client-secret"}
SCREENSCRAPER_DEV_ID=${config.sops.placeholder."services/romm/screenscraper/dev/id"}
SCREENSCRAPER_DEV_PASSWORD=${config.sops.placeholder."services/romm/screenscraper/dev/password"}
SCREENSCRAPER_USER=${config.sops.placeholder."services/romm/screenscraper/user"}
SCREENSCRAPER_PASSWORD=${config.sops.placeholder."services/romm/screenscraper/password"}
RETROACHIEVEMENTS_API_KEY=${config.sops.placeholder."services/romm/retroachievements/api-key"}
STEAMGRIDDB_API_KEY=${config.sops.placeholder."services/romm/steamgriddb/api-key"}
'';
};
};
}
+1 -1
View File
@@ -4,7 +4,7 @@
... ...
}: }:
let let
cfg = config.guests.valheim; # NOLINT(let_order) cfg = config.guests.valheim;
steamDir = "/data/steamcmd"; steamDir = "/data/steamcmd";
installDir = "/data/server"; installDir = "/data/server";
stateDir = "/data/state"; stateDir = "/data/state";
+23 -3
View File
@@ -1,5 +1,6 @@
{ {
inputs, inputs,
util,
... ...
}: }:
# neogaia — Dell XPS 13 9380 laptop. # neogaia — Dell XPS 13 9380 laptop.
@@ -14,8 +15,9 @@
modules.host.cachyos.enable = true; modules.host.cachyos.enable = true;
# So wifi can be joined from the console. services.xserver.xkb.options = "caps:swapescape";
networking.networkmanager.enable = true;
modules.network.enable = true;
registry.address.neogaia.self = "10.23.50.146"; registry.address.neogaia.self = "10.23.50.146";
@@ -38,6 +40,24 @@
modules.desktop.enable = true; modules.desktop.enable = true;
modules.desktop.apps.firefox.uiScale = "1.25"; modules.desktop.apps.firefox.uiScale = "1.25";
modules.desktop.apps.obsidian.enable = true; modules.desktop.apps.obsidian.enable = true;
modules.desktop.apps.steam.enable = true;
registry.waybar.neogaia.battery = {
order = 70;
settings = {
format = "{icon} {capacity}%";
format-charging = "${util.glyph "f0e7"} {capacity}%";
format-icons = [
(util.glyph "f244")
(util.glyph "f243")
(util.glyph "f242")
(util.glyph "f241")
(util.glyph "f240")
];
states = {
warning = 20;
critical = 10;
};
};
};
} }
+45 -31
View File
@@ -29,6 +29,14 @@
registry.address.pikachu.self = "10.23.10.102"; registry.address.pikachu.self = "10.23.10.102";
guests.adguard = {
enable = true;
vlan = 20;
mac = "bc:24:11:91:60:bf";
address = "10.23.20.33";
adminPasswordHash = "$2b$12$wariglnrCvJOnh4b8KnB9eDX4RdQRaaTZtyXMUOilaYSn7xTR0g1e";
};
guests.valheim = { guests.valheim = {
enable = true; enable = true;
vlan = 20; vlan = 20;
@@ -71,22 +79,6 @@
}; };
}; };
guests.actualbudget = {
enable = true;
vlan = 20;
mac = "BC:24:11:C1:CD:28";
dataPath = "/pikachu/data/actualbudget";
address = "10.23.20.42";
reverseProxy = {
enable = true;
route = {
domain = "budget.alexion.dev";
protocol = "https";
port = 5006;
};
};
};
guests.navidrome = { guests.navidrome = {
enable = true; enable = true;
vlan = 20; vlan = 20;
@@ -104,6 +96,42 @@
}; };
}; };
guests.gitea = {
enable = true;
vlan = 20;
address = "10.23.20.206";
dataPath = "/pikachu/data/gitea";
reverseProxy = {
enable = true;
route = {
domain = "git.alexion.dev";
protocol = "https";
port = 3000;
};
};
};
guests.romm = {
enable = true;
vlan = 20;
address = "10.23.20.112";
dataPath = "/pikachu/data/romm";
postgresqlPath = "/pikachu/data/romm/postgresql";
redisPath = "/pikachu/data/romm/redis";
romsPath = "/pikachu/media/games/emulation/roms";
biosPath = "/pikachu/media/games/emulation/bios";
usersPath = "/pikachu/media/games/emulation/users";
reverseProxy = {
enable = true;
route = {
domain = "games.alexion.dev";
protocol = "https";
port = 80;
clientMaxBodySize = "0";
};
};
};
guests.reverse-proxy = { guests.reverse-proxy = {
enable = true; enable = true;
vlan = 20; vlan = 20;
@@ -145,35 +173,21 @@
"/" = { "/" = {
hostPath = "/pikachu/data/copyparty/root"; hostPath = "/pikachu/data/copyparty/root";
path = "/srv"; path = "/srv";
access.r = [ "alexion" ];
readOnly = true; readOnly = true;
}; };
"/inbox" = { "/inbox" = {
hostPath = "/pikachu/__inbox"; hostPath = "/pikachu/__inbox";
path = "/pikachu/__inbox"; path = "/pikachu/__inbox";
access.A = [ "alexion" ];
flags = [
"d2d"
"d2t"
"dthumb"
];
}; };
"/media" = { "/media" = {
hostPath = "/pikachu/media"; hostPath = "/pikachu/media";
path = "/pikachu/media"; path = "/pikachu/media";
access.A = [ "alexion" ];
flags = [
"d2d"
"d2t"
"dthumb"
];
}; };
"/opds" = { "/opds" = {
hostPath = "/pikachu/data/opds"; hostPath = "/pikachu/data/opds";
path = "/pikachu/data/opds"; path = "/pikachu/data/opds";
access.r = [ "alexion" ];
readOnly = true; readOnly = true;
flags = [ "opds" ]; flags.opds = true;
}; };
}; };
}; };
+5 -4
View File
@@ -21,7 +21,7 @@
enable32Bit = true; enable32Bit = true;
}; };
networking.networkmanager.enable = true; modules.network.enable = true;
services.logind.settings.Login = { services.logind.settings.Login = {
HandlePowerKey = "ignore"; HandlePowerKey = "ignore";
@@ -44,22 +44,23 @@
modules.desktop.enable = true; modules.desktop.enable = true;
modules.desktop.apps.obsidian.enable = true; modules.desktop.apps.obsidian.enable = true;
modules.desktop.apps.r2modman.enable = true; modules.desktop.apps.r2modman.enable = true;
modules.desktop.emulation.enable = true;
modules.desktop.apps.signal.enable = true; modules.desktop.apps.signal.enable = true;
modules.desktop.apps.steam.enable = true; modules.desktop.apps.steam.enable = true;
modules.desktop.apps.vencord.enable = true; modules.desktop.apps.discord.enable = true;
home-manager.users.${config.user.name}.wayland.windowManager.hyprland.settings.monitor = [ home-manager.users.${config.user.name}.wayland.windowManager.hyprland.settings.monitor = [
{ {
output = "HDMI-A-1"; output = "HDMI-A-1";
mode = "1920x1080@120"; mode = "1920x1080@120";
position = "0x0"; position = "-1080x0";
scale = 1; scale = 1;
transform = 3; transform = 3;
} }
{ {
output = "DP-3"; output = "DP-3";
mode = "2560x1440@239.96"; mode = "2560x1440@239.96";
position = "1080x0"; position = "0x0";
scale = 1; scale = 1;
} }
]; ];
@@ -0,0 +1,23 @@
{
config,
lib,
pkgs,
util,
...
}:
# Official Discord provides chat, voice, and screen sharing.
let
user = config.user.name;
in
{
options.modules.desktop.apps.discord.enable = lib.mkEnableOption "official Discord";
config = lib.mkIf config.modules.desktop.apps.discord.enable {
home-manager.users.${user}.home.packages = [ pkgs.discord ];
registry.window-icon.${config.networking.hostName}.discord = {
class = "[Dd]iscord";
icon = util.glyph "f1ff";
};
};
}
@@ -3,11 +3,12 @@
inputs, inputs,
lib, lib,
pkgs, pkgs,
util,
... ...
}: }:
# Configures Firefox as the desktop browser. # Configures Firefox as the desktop browser.
let let
cfg = config.modules.desktop.apps.firefox; # NOLINT(let_order) cfg = config.modules.desktop.apps.firefox;
in in
{ {
options.modules.desktop.apps.firefox = { options.modules.desktop.apps.firefox = {
@@ -26,6 +27,11 @@ in
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
registry.window-icon.${config.networking.hostName}.firefox = {
class = ".*[Ff]irefox.*";
icon = util.glyph "f269";
};
home-manager.users.${config.user.name} = hm: { home-manager.users.${config.user.name} = hm: {
programs.firefox = { programs.firefox = {
enable = true; enable = true;
@@ -61,6 +67,8 @@ in
# Stylix uses a near-white selection background. # Stylix uses a near-white selection background.
# Use the Nord selection color because its text stays readable. # Use the Nord selection color because its text stays readable.
# Home Manager writes extension settings through Firefox's legacy storage backend.
# Extension settings disable `ExtensionStorageIDB` for the whole profile.
extensions.settings."FirefoxColor@mozilla.com".settings.theme.colors.popup_highlight = extensions.settings."FirefoxColor@mozilla.com".settings.theme.colors.popup_highlight =
let let
c = hm.config.lib.stylix.colors; c = hm.config.lib.stylix.colors;
@@ -2,6 +2,7 @@
config, config,
lib, lib,
pkgs, pkgs,
util,
... ...
}: }:
# Ghostty as the desktop terminal. # Ghostty as the desktop terminal.
@@ -16,10 +17,15 @@ in
keys = "SUPER + Return"; keys = "SUPER + Return";
action = { action = {
kind = "exec"; kind = "exec";
command = "${pkgs.ghostty}/bin/ghostty"; command = lib.getExe pkgs.ghostty;
}; };
}; };
registry.window-icon.${config.networking.hostName}.ghostty = {
class = "com.mitchellh.ghostty";
icon = util.glyph "f120";
};
home-manager.users.${user}.home.packages = [ pkgs.ghostty ]; home-manager.users.${user}.home.packages = [ pkgs.ghostty ];
}; };
} }
@@ -2,6 +2,7 @@
config, config,
lib, lib,
pkgs, pkgs,
util,
... ...
}: }:
# Obsidian as the desktop note-taking vault. # Obsidian as the desktop note-taking vault.
@@ -14,5 +15,10 @@ in
config = lib.mkIf config.modules.desktop.apps.obsidian.enable { config = lib.mkIf config.modules.desktop.apps.obsidian.enable {
home-manager.users.${user}.home.packages = [ pkgs.obsidian ]; home-manager.users.${user}.home.packages = [ pkgs.obsidian ];
registry.window-icon.${config.networking.hostName}.obsidian = {
class = "obsidian";
icon = util.glyph "f02d";
};
}; };
} }
@@ -2,6 +2,7 @@
config, config,
lib, lib,
pkgs, pkgs,
util,
... ...
}: }:
# Signal desktop messenger. # Signal desktop messenger.
@@ -13,5 +14,10 @@ in
config = lib.mkIf config.modules.desktop.apps.signal.enable { config = lib.mkIf config.modules.desktop.apps.signal.enable {
home-manager.users.${user}.home.packages = [ pkgs.signal-desktop ]; home-manager.users.${user}.home.packages = [ pkgs.signal-desktop ];
registry.window-icon.${config.networking.hostName}.signal = {
class = "[Ss]ignal";
icon = util.glyph "f4ad";
};
}; };
} }
+11 -3
View File
@@ -2,6 +2,7 @@
config, config,
lib, lib,
pkgs, pkgs,
util,
... ...
}: }:
# Steam game launcher and runtime integration. # Steam game launcher and runtime integration.
@@ -13,6 +14,7 @@
programs.steam = { programs.steam = {
enable = true; enable = true;
remotePlay.openFirewall = true;
package = pkgs.steam.override { package = pkgs.steam.override {
extraEnv.STEAM_FORCE_DESKTOPUI_SCALING = "1.5"; extraEnv.STEAM_FORCE_DESKTOPUI_SCALING = "1.5";
}; };
@@ -20,8 +22,14 @@
hardware.steam-hardware.enable = true; hardware.steam-hardware.enable = true;
environment.systemPackages = [ programs.gamescope = {
pkgs.gamescope enable = true;
]; capSysNice = true;
};
registry.window-icon.${config.networking.hostName}.steam = {
class = "[Ss]team";
icon = util.glyph "f1b6";
};
}; };
} }
@@ -1,18 +0,0 @@
{
config,
lib,
pkgs,
...
}:
# Vesktop, a Discord client with Vencord built in.
let
user = config.user.name;
in
{
options.modules.desktop.apps.vencord.enable =
lib.mkEnableOption "Vesktop, a Discord client with Vencord built in";
config = lib.mkIf config.modules.desktop.apps.vencord.enable {
home-manager.users.${user}.home.packages = [ pkgs.vesktop ];
};
}
@@ -23,5 +23,6 @@
modules.desktop.utilities.screenshot.enable = lib.mkDefault true; modules.desktop.utilities.screenshot.enable = lib.mkDefault true;
modules.desktop.utilities.theming.enable = lib.mkDefault true; modules.desktop.utilities.theming.enable = lib.mkDefault true;
modules.desktop.utilities.userdirs.enable = lib.mkDefault true; modules.desktop.utilities.userdirs.enable = lib.mkDefault true;
registry.env.${config.networking.hostName}.NIXOS_OZONE_WL = "1";
}; };
} }
@@ -0,0 +1,36 @@
{
config,
lib,
...
}:
# Shared directories for emulators.
let
user = config.user.name;
directory = "/home/${user}/emulation";
in
{
options.modules.desktop.emulation.enable = lib.mkEnableOption "shared emulation directories";
config = lib.mkIf config.modules.desktop.emulation.enable {
modules.desktop.emulation.retroarch = {
enable = lib.mkDefault true;
browserDirectory = "${directory}/roms";
};
home-manager.users.${user} = hm: {
home.file = {
".config/retroarch/saves".source = hm.config.lib.file.mkOutOfStoreSymlink "${directory}/saves";
".config/retroarch/states".source = hm.config.lib.file.mkOutOfStoreSymlink "${directory}/states";
".config/retroarch/system".source = hm.config.lib.file.mkOutOfStoreSymlink "${directory}/bios";
};
systemd.user.tmpfiles.rules = map (path: "d ${path} 0700 - - -") [
directory
"${directory}/bios"
"${directory}/roms"
"${directory}/saves"
"${directory}/states"
];
};
};
}
@@ -0,0 +1,109 @@
{
config,
lib,
pkgs,
util,
...
}:
# RetroArch with the selected PlayStation and Sega Saturn cores.
let
cfg = config.modules.desktop.emulation.retroarch;
user = config.user.name;
in
{
options.modules.desktop.emulation.retroarch = {
enable = lib.mkEnableOption "RetroArch with PlayStation and Sega Saturn cores";
browserDirectory = lib.mkOption {
type = lib.types.str;
default = "";
description = "Directory where RetroArch starts its content browser.";
};
};
config = lib.mkIf cfg.enable {
sops.secrets =
lib.genAttrs
[
"retroarch/romm/user"
"retroarch/romm/password"
"retroarch/retroachievements/user"
"retroarch/retroachievements/password"
]
(_: {
sopsFile = ../../../secrets + "/${config.networking.hostName}.yaml";
});
sops.templates.retroarch-credentials = {
owner = user;
mode = "0400";
content = ''
webdav_username = "${config.sops.placeholder."retroarch/romm/user"}"
webdav_password = "${config.sops.placeholder."retroarch/romm/password"}"
cheevos_username = "${config.sops.placeholder."retroarch/retroachievements/user"}"
cheevos_password = "${config.sops.placeholder."retroarch/retroachievements/password"}"
'';
};
home-manager.users.${user} = {
home.file.".config/retroarch/retroarch.cfg" = {
force = true;
text = ''
config_save_on_exit = "false"
#include "${config.sops.templates.retroarch-credentials.path}"
'';
};
home.packages = [
(pkgs.wrapRetroArch {
cores = with pkgs.libretro; [
beetle-psx-hw
beetle-saturn
];
settings = {
savefiles_in_content_dir = "false";
savestates_in_content_dir = "false";
system_directory = "/home/${user}/.config/retroarch/system";
video_fullscreen = "true";
sort_savefiles_enable = "true";
sort_savestates_enable = "true";
cloud_sync_enable = "true";
cloud_sync_driver = "webdav";
webdav_url = "https://games.alexion.dev/api/sync/retroarch/";
cloud_sync_sync_saves = "true";
cloud_sync_sync_configs = "true";
cloud_sync_sync_thumbs = "false";
cloud_sync_sync_system = "false";
cloud_sync_sync_mode = "0";
cloud_sync_destructive = "false";
cheevos_enable = "true";
cheevos_hardcore_mode_enable = "false";
menu_driver = "xmb";
menu_shader_pipeline = "1";
xmb_menu_color_theme = "19";
content_show_add_entry = "0";
content_show_contentless_cores = "0";
content_show_explore = "false";
content_show_favorites = "false";
content_show_history = "false";
content_show_images = "false";
content_show_playlists = "false";
content_show_video = "false";
menu_icon_thumbnails = "3";
menu_thumbnails = "0";
network_on_demand_thumbnails = "true";
netplay_nickname = user;
}
// lib.optionalAttrs (cfg.browserDirectory != "") {
rgui_browser_directory = cfg.browserDirectory;
};
})
];
};
registry.window-icon.${config.networking.hostName}.retroarch = {
class = "com.libretro.RetroArch";
icon = util.glyph "f11b";
};
};
}
@@ -1,6 +1,7 @@
{ {
config, config,
lib, lib,
util,
... ...
}: }:
# The Hyprland compositor. # The Hyprland compositor.
@@ -36,6 +37,7 @@
config = { config = {
input = { input = {
kb_layout = config.services.xserver.xkb.layout; kb_layout = config.services.xserver.xkb.layout;
kb_options = config.services.xserver.xkb.options;
repeat_delay = 250; repeat_delay = 250;
repeat_rate = 45; repeat_rate = 45;
accel_profile = "flat"; accel_profile = "flat";
@@ -63,6 +65,13 @@
dwindle.preserve_split = true; dwindle.preserve_split = true;
}; };
env = lib.mapAttrsToList (name: value: {
_args = [
name
value
];
}) (lib.attrByPath [ config.networking.hostName ] { } config.registry.env);
bind = lib.mapAttrsToList (_name: keybind: { bind = lib.mapAttrsToList (_name: keybind: {
_args = [ _args = [
keybind.keys keybind.keys
@@ -111,6 +120,9 @@
] ]
++ lib.optional keybind.repeating { ++ lib.optional keybind.repeating {
repeating = true; repeating = true;
}
++ lib.optional keybind.locked {
locked = true;
}; };
}) (lib.attrByPath [ config.networking.hostName ] { } config.registry.keybind); }) (lib.attrByPath [ config.networking.hostName ] { } config.registry.keybind);
}; };
@@ -217,5 +229,18 @@
}; };
} }
]; ];
registry.waybar.${config.networking.hostName}."hyprland/workspaces" = {
position = "left";
order = 10;
settings = {
format = "{id} {windows}";
format-window-separator = " ";
window-rewrite-default = util.glyph "f2d0";
window-rewrite = lib.mapAttrs' (
_name: windowIcon: lib.nameValuePair "class<${windowIcon.class}>" windowIcon.icon
) (lib.attrByPath [ config.networking.hostName ] { } config.registry.window-icon);
};
};
}; };
} }
@@ -5,50 +5,32 @@
... ...
}: }:
# hypridle: idle-triggered locking and display power management. # hypridle: idle-triggered locking and display power management.
let
cfg = config.modules.desktop.session.hyprland.hypridle; # NOLINT(let_order)
# The guard drops the call when a locker is already up, so no idle trigger
# stacks a second hyprlock over the first.
lockCmd = "${pkgs.procps}/bin/pidof hyprlock || ${hyprlock}";
user = config.user.name;
hyprctl = "${config.programs.hyprland.package}/bin/hyprctl";
hyprlock = "${config.home-manager.users.${user}.programs.hyprlock.package}/bin/hyprlock";
in
{ {
options.modules.desktop.session.hyprland.hypridle = { options.modules.desktop.session.hyprland.hypridle.enable =
enable = lib.mkEnableOption "hypridle idle management"; lib.mkEnableOption "hypridle idle management";
lockTimeout = lib.mkOption { config = lib.mkIf config.modules.desktop.session.hyprland.hypridle.enable {
type = lib.types.ints.positive;
default = 300;
description = "Seconds of inactivity before the screen locks.";
};
};
config = lib.mkIf cfg.enable {
# Closing the lid suspends, and every suspend locks first through the # Closing the lid suspends, and every suspend locks first through the
# before_sleep_cmd below, so the lid always lands at a locked screen. # before_sleep_cmd below, so the lid always lands at a locked screen.
services.logind.settings.Login.HandleLidSwitch = "suspend"; services.logind.settings.Login.HandleLidSwitch = "suspend";
home-manager.users.${user}.services.hypridle = { home-manager.users.${config.user.name}.services.hypridle = {
enable = true; enable = true;
settings = { settings = {
general = { general = {
lock_cmd = lockCmd; # The guard drops the call when a locker is already up, so no idle
# trigger stacks a second hyprlock over the first.
lock_cmd = "${lib.getExe' pkgs.procps "pidof"} hyprlock || ${lib.getExe pkgs.hyprlock}";
before_sleep_cmd = "loginctl lock-session"; before_sleep_cmd = "loginctl lock-session";
# Waking pokes the compositor in case firmware leaves displays dark. # Waking pokes the compositor in case firmware leaves displays dark.
after_sleep_cmd = "${hyprctl} dispatch dpms on"; after_sleep_cmd = "${lib.getExe' config.programs.hyprland.package "hyprctl"} dispatch 'hl.dsp.dpms({ action = \"enable\" })'";
}; };
listener = [ listener = [
# Lock on idle. # Lock on idle.
{ {
timeout = cfg.lockTimeout; timeout = 300;
on-timeout = "loginctl lock-session"; on-timeout = "loginctl lock-session";
} }
]; ];
@@ -2,44 +2,54 @@
config, config,
lib, lib,
pkgs, pkgs,
util,
... ...
}: }:
# The lock screen: a hyprlock session-lock surface the compositor owns. # The lock screen: a hyprlock session-lock surface the compositor owns.
let let
user = config.user.name; sleepIcon = util.glyph [
"db81"
# The hyprlock this module installs, used by the lock keybind below. "dcb2"
hyprlock = "${config.home-manager.users.${user}.programs.hyprlock.package}/bin/hyprlock"; ];
sleepOffIcon = util.glyph [
sleepIcon = builtins.fromJSON ''"\udb81\udcb2"''; "db81"
sleepOffIcon = builtins.fromJSON ''"\udb81\udcb3"''; "dcb3"
];
idleLockToggle = pkgs.writeShellScript "lockscreen-idle-inhibit-toggle" '' idleLockToggle = pkgs.writeShellScript "lockscreen-idle-inhibit-toggle" ''
unit=lockscreen-idle-inhibit.service unit=lockscreen-idle-inhibit.service
refresh_waybar() { refresh_waybar() {
${pkgs.procps}/bin/pkill -RTMIN+9 waybar >/dev/null 2>&1 || true ${lib.getExe' pkgs.procps "pkill"} -RTMIN+9 waybar >/dev/null 2>&1 || true
} }
if ${pkgs.systemd}/bin/systemctl --user is-active --quiet "$unit"; then if ${lib.getExe' pkgs.systemd "systemctl"} --user is-active --quiet "$unit"; then
${pkgs.systemd}/bin/systemctl --user stop "$unit" ${lib.getExe' pkgs.systemd "systemctl"} --user stop "$unit"
refresh_waybar refresh_waybar
${pkgs.swayosd}/bin/swayosd-client --custom-message "${sleepIcon}" ${lib.getExe' pkgs.swayosd "swayosd-client"} --custom-message "${sleepIcon}"
exit 0 exit 0
fi fi
if ${pkgs.systemd}/bin/systemd-run \ if ${lib.getExe' pkgs.systemd "systemd-run"} \
--user \ --user \
--collect \ --collect \
--unit=lockscreen-idle-inhibit \ --unit=lockscreen-idle-inhibit \
--description="Disable idle-triggered screen locking" \ --description="Disable idle-triggered screen locking" \
${pkgs.systemd}/bin/systemd-inhibit \ ${lib.getExe' pkgs.systemd "systemd-inhibit"} \
--what=idle \ --what=idle \
--who=lockscreen-hotkey \ --who=lockscreen-hotkey \
--why="lock screen disabled by hotkey" \ --why="lock screen disabled by hotkey" \
${pkgs.coreutils}/bin/sleep infinity >/dev/null; then ${lib.getExe' pkgs.coreutils "sleep"} infinity >/dev/null; then
refresh_waybar refresh_waybar
${pkgs.swayosd}/bin/swayosd-client --custom-message "${sleepOffIcon}" ${lib.getExe' pkgs.swayosd "swayosd-client"} --custom-message "${sleepOffIcon}"
fi
'';
idleLockStatus = pkgs.writeShellScript "waybar-idle-lock-status" ''
if ${lib.getExe' pkgs.systemd "systemctl"} --user is-active --quiet lockscreen-idle-inhibit.service; then
printf '{"text":"${sleepOffIcon}","tooltip":"Idle locking inhibited","class":"inhibited"}\n'
else
printf '{"text":"","class":"idle"}\n'
fi fi
''; '';
in in
@@ -48,7 +58,7 @@ in
lib.mkEnableOption "the hyprlock lock screen"; lib.mkEnableOption "the hyprlock lock screen";
config = lib.mkIf config.modules.desktop.session.hyprland.hyprlock.enable { config = lib.mkIf config.modules.desktop.session.hyprland.hyprlock.enable {
home-manager.users.${user} = { home-manager.users.${config.user.name} = {
# Colors and the lock-screen background come from Stylix's hyprlock target, # Colors and the lock-screen background come from Stylix's hyprlock target,
# so only geometry and behaviour are set here. # so only geometry and behaviour are set here.
programs.hyprlock = { programs.hyprlock = {
@@ -81,16 +91,36 @@ in
}; };
}; };
}; };
};
# Lock on Super+X. registry.keybind.${config.networking.hostName} = {
# The guard drops the keypress when a locker is already up, so a second hyprlock-lock = {
# hyprlock never stacks over the first. keys = "SUPER + X";
/* action = {
wayland.windowManager.hyprland.settings.bind = [ kind = "exec";
"$mod, X, exec, ${pkgs.procps}/bin/pidof hyprlock || ${hyprlock}" # The guard drops the call when a locker is already up, so no manual
"$mod CTRL, X, exec, ${idleLockToggle}" # trigger stacks a second hyprlock over the first.
]; command = "${lib.getExe' pkgs.procps "pidof"} hyprlock || ${lib.getExe pkgs.hyprlock}";
*/ };
};
hyprlock-toggle-idle-inhibit = {
keys = "SUPER + CTRL + X";
action = {
kind = "exec";
command = "${idleLockToggle}";
};
};
};
registry.waybar.${config.networking.hostName}."custom/idle-lock" = {
order = 20;
settings = {
return-type = "json";
exec = "${idleLockStatus}";
interval = "once";
signal = 9;
};
}; };
}; };
} }
@@ -13,9 +13,13 @@
config = lib.mkIf config.modules.desktop.session.login.enable { config = lib.mkIf config.modules.desktop.session.login.enable {
services.greetd = { services.greetd = {
enable = true; enable = true;
settings.default_session.command = settings.default_session.command = lib.escapeShellArgs [
"${lib.getExe pkgs.tuigreet} --time --remember " (lib.getExe pkgs.tuigreet)
+ "--cmd 'uwsm start -e -D Hyprland hyprland.desktop'"; "--time"
"--remember"
"--cmd"
"${lib.getExe config.programs.uwsm.package} start -e -D Hyprland hyprland.desktop"
];
}; };
}; };
} }
+31 -11
View File
@@ -2,19 +2,29 @@
config, config,
lib, lib,
pkgs, pkgs,
util,
... ...
}: }:
# mako as the notification daemon: toasts, a do-not-disturb mode, and history recall. # mako as the notification daemon: toasts, a do-not-disturb mode, and history recall.
let let
user = config.user.name; dndStatus = pkgs.writeShellScript "waybar-dnd-status" ''
if ${lib.getExe' pkgs.mako "makoctl"} mode 2>/dev/null | ${lib.getExe pkgs.gnugrep} -qx dnd; then
printf '{"text":"${util.glyph "f1f6"}","tooltip":"Do not disturb: on","class":"dnd"}\n'
else
printf '{"text":"${util.glyph "f0f3"}","tooltip":"Notifications on","class":"active"}\n'
fi
'';
makoctl = "${pkgs.mako}/bin/makoctl"; dndToggle = pkgs.writeShellScript "waybar-dnd-toggle" ''
${lib.getExe' pkgs.mako "makoctl"} mode -t dnd >/dev/null 2>&1
${lib.getExe' pkgs.procps "pkill"} -RTMIN+8 waybar
'';
in in
{ {
options.modules.desktop.session.mako.enable = lib.mkEnableOption "the mako notification daemon"; options.modules.desktop.session.mako.enable = lib.mkEnableOption "the mako notification daemon";
config = lib.mkIf config.modules.desktop.session.mako.enable { config = lib.mkIf config.modules.desktop.session.mako.enable {
home-manager.users.${user} = { home-manager.users.${config.user.name} = {
# Colors and the popup font come from Stylix's mako target, so only # Colors and the popup font come from Stylix's mako target, so only
# behaviour is set here. # behaviour is set here.
services.mako = { services.mako = {
@@ -31,15 +41,25 @@ in
"mode=dnd".invisible = true; "mode=dnd".invisible = true;
}; };
}; };
};
# Recall the last notification from history, keyboard-only like the rest registry.keybind.${config.networking.hostName}.mako-history = {
# of the session. keys = "SUPER + N";
# $mod is defined by the compositor config these binds share. action = {
/* kind = "exec";
wayland.windowManager.hyprland.settings.bind = [ command = "${lib.getExe' pkgs.mako "makoctl"} restore";
"$mod, N, exec, ${makoctl} restore" };
]; };
*/
registry.waybar.${config.networking.hostName}."custom/dnd" = {
order = 80;
settings = {
return-type = "json";
exec = "${dndStatus}";
on-click = "${dndToggle}";
interval = "once";
signal = 8;
};
}; };
}; };
} }
+33 -20
View File
@@ -6,19 +6,17 @@
}: }:
# rofi as the desktop launcher and dmenu-style menu frontend. # rofi as the desktop launcher and dmenu-style menu frontend.
let let
user = config.user.name;
# A session menu built on the same themed rofi, so the power actions look # A session menu built on the same themed rofi, so the power actions look
# like every other menu the launcher drives. # like every other menu the launcher drives.
powerMenu = pkgs.writeShellScript "rofi-power-menu" '' powerMenu = pkgs.writeShellScript "rofi-power-menu" ''
chosen=$(printf '%s\n' Lock Suspend 'Log out' Reboot 'Shut down' \ chosen=$(printf '%s\n' Lock Suspend 'Log out' Reboot 'Shut down' \
| ${pkgs.rofi}/bin/rofi -dmenu -i -p Power) | ${lib.getExe pkgs.rofi} -dmenu -i -p Power)
case "$chosen" in case "$chosen" in
Lock) ${pkgs.systemd}/bin/loginctl lock-session ;; Lock) ${lib.getExe' pkgs.systemd "loginctl"} lock-session ;;
Suspend) ${pkgs.systemd}/bin/systemctl suspend ;; Suspend) ${lib.getExe' pkgs.systemd "systemctl"} suspend ;;
'Log out') ${pkgs.systemd}/bin/loginctl terminate-session "$XDG_SESSION_ID" ;; 'Log out') ${lib.getExe' pkgs.systemd "loginctl"} terminate-session "$XDG_SESSION_ID" ;;
Reboot) ${pkgs.systemd}/bin/systemctl reboot ;; Reboot) ${lib.getExe' pkgs.systemd "systemctl"} reboot ;;
'Shut down') ${pkgs.systemd}/bin/systemctl poweroff ;; 'Shut down') ${lib.getExe' pkgs.systemd "systemctl"} poweroff ;;
esac esac
''; '';
in in
@@ -26,28 +24,43 @@ in
options.modules.desktop.session.rofi.enable = lib.mkEnableOption "the rofi launcher"; options.modules.desktop.session.rofi.enable = lib.mkEnableOption "the rofi launcher";
config = lib.mkIf config.modules.desktop.session.rofi.enable { config = lib.mkIf config.modules.desktop.session.rofi.enable {
home-manager.users.${user} = { home-manager.users.${config.user.name} = hm: {
# No theme is set here: Stylix's rofi target supplies the Nord one. # Stylix supplies the Nord theme.
programs.rofi = { programs.rofi = {
enable = true; enable = true;
# Application launch is the only mode, kept minimal so the prompt opens # Application launch is the only mode, kept minimal so the prompt opens
# as fast as rofi can read the desktop entries. # as fast as rofi can read the desktop entries.
# Icons are off: resolving one per entry is the bulk of drun's startup. # Icons are off: resolving one per entry is the bulk of drun's startup.
extraConfig = { settings = {
font = lib.mkForce "JetBrains Mono 12";
modi = "drun"; modi = "drun";
show-icons = false; show-icons = false;
}; };
theme.window = {
border = hm.config.lib.formats.rasi.mkLiteral "2px";
border-color = hm.config.lib.formats.rasi.mkLiteral "#FFFFFF";
border-radius = hm.config.lib.formats.rasi.mkLiteral "8px";
};
};
}; };
# The launcher and the session menu, kept next to the tool they drive. registry.keybind.${config.networking.hostName} = {
# $mod is defined by the compositor config these binds share. rofi-launcher = {
/* keys = "SUPER + R";
wayland.windowManager.hyprland.settings.bind = [ action = {
"$mod, R, exec, ${pkgs.rofi}/bin/rofi -show drun" kind = "exec";
"$mod SHIFT, X, exec, ${powerMenu}" command = "${lib.getExe pkgs.rofi} -show drun";
]; };
*/ };
rofi-power-menu = {
keys = "SUPER + SHIFT + X";
action = {
kind = "exec";
command = "${powerMenu}";
};
};
}; };
}; };
} }
+24 -202
View File
@@ -6,97 +6,19 @@
}: }:
# Waybar: a top status bar reading system state at a glance. # Waybar: a top status bar reading system state at a glance.
let let
vpnClient = config.modules.network.vpn-client; moduleNames =
position:
# A Nerd Font Private-Use-Area codepoint as a literal character, decoded map (entry: entry.name) (
# through JSON so the glyph survives as bytes rather than an editor paste. lib.sort (left: right: left.module.order < right.module.order) (
g = code: builtins.fromJSON ''"\u${code}"''; lib.filter (entry: entry.module.position == position) moduleEntries
user = config.user.name;
sleepOffIcon = builtins.fromJSON ''"\udb81\udcb3"'';
# Renders and toggles mako's do-not-disturb mode.
# With no mako daemon answering, the status reads "notifications on", keeping
# the widget inert rather than broken.
dndStatus = pkgs.writeShellScript "waybar-dnd-status" ''
if ${pkgs.mako}/bin/makoctl mode 2>/dev/null | ${pkgs.gnugrep}/bin/grep -qx dnd; then
printf '{"text":"${g "f1f6"}","tooltip":"Do not disturb: on","class":"dnd"}\n'
else
printf '{"text":"${g "f0f3"}","tooltip":"Notifications on","class":"active"}\n'
fi
'';
dndToggle = pkgs.writeShellScript "waybar-dnd-toggle" ''
${pkgs.mako}/bin/makoctl mode -t dnd >/dev/null 2>&1
${pkgs.procps}/bin/pkill -RTMIN+8 waybar
'';
# Lit while a wf-recorder capture is running.
# Empty text collapses the widget when idle, so it shows nothing until then.
recStatus = pkgs.writeShellScript "waybar-recording-status" ''
if ${pkgs.procps}/bin/pgrep -x wf-recorder >/dev/null; then
printf '{"text":"${g "f03d"}","tooltip":"Recording","class":"recording"}\n'
else
printf '{"text":"","class":"idle"}\n'
fi
'';
idleLockStatus = pkgs.writeShellScript "waybar-idle-lock-status" ''
if ${pkgs.systemd}/bin/systemctl --user is-active --quiet lockscreen-idle-inhibit.service; then
printf '{"text":"${sleepOffIcon}","tooltip":"Idle locking inhibited","class":"inhibited"}\n'
else
printf '{"text":"","class":"idle"}\n'
fi
'';
vpnStatus = pkgs.writeShellScript "waybar-vpn-status" ''
interface=${lib.escapeShellArg vpnClient.interface}
if ! ${pkgs.iproute2}/bin/ip link show dev "$interface" >/dev/null 2>&1; then
printf '{"text":"","class":"idle"}\n'
exit 0
fi
ipaddr=$(${pkgs.iproute2}/bin/ip -4 -o addr show dev "$interface" | ${pkgs.gawk}/bin/awk '{ print $4; exit }')
${pkgs.jq}/bin/jq -cn \
--arg text "󰲝" \
--arg tooltip "VPN $interface: ''${ipaddr:-no IPv4}" \
--arg class "active" \
'{ text: $text, tooltip: $tooltip, class: $class }'
'';
networkStatus = pkgs.writeShellScript "waybar-network-status" ''
active=$(
${pkgs.networkmanager}/bin/nmcli -t -f DEVICE,TYPE,STATE,CONNECTION device status \
| ${pkgs.gawk}/bin/awk -F: '$3 == "connected" && $2 != "loopback" { print; exit }'
) )
);
if [ -z "$active" ]; then moduleEntries = lib.mapAttrsToList (name: module: {
${pkgs.jq}/bin/jq -cn \ inherit name module;
--arg text "${g "f127"} off" \ }) modules;
--arg tooltip "Network disconnected" \
--arg class "disconnected" \
'{ text: $text, tooltip: $tooltip, class: $class }'
exit 0
fi
IFS=: read -r device type _state connection <<< "$active" modules = lib.attrByPath [ config.networking.hostName ] { } config.registry.waybar;
case "$type" in
wifi) icon="${g "f1eb"}" ;;
ethernet) icon="LAN" ;;
*) icon="NET" ;;
esac
ipaddr=$(${pkgs.iproute2}/bin/ip -4 -o addr show dev "$device" | ${pkgs.gawk}/bin/awk '{ print $4; exit }')
${pkgs.jq}/bin/jq -cn \
--arg text "$icon $connection" \
--arg tooltip "$device: ''${ipaddr:-no IPv4}" \
--arg class "$type" \
'{ text: $text, tooltip: $tooltip, class: $class }'
'';
in in
{ {
options.modules.desktop.session.waybar.enable = lib.mkEnableOption "the Waybar status bar"; options.modules.desktop.session.waybar.enable = lib.mkEnableOption "the Waybar status bar";
@@ -106,64 +28,35 @@ in
# codepoints Stylix's monospace font does not carry. # codepoints Stylix's monospace font does not carry.
fonts.packages = [ pkgs.nerd-fonts.symbols-only ]; fonts.packages = [ pkgs.nerd-fonts.symbols-only ];
home-manager.users.${user}.programs.waybar = { home-manager.users.${config.user.name}.programs.waybar = {
enable = true; enable = true;
package = pkgs.alexion.waybar;
# A user service bound to graphical-session.target, which uwsm activates, # A user service bound to graphical-session.target, which uwsm activates,
# so the bar comes up with the session and no compositor exec-once. # so the bar comes up with the session and no compositor exec-once.
systemd.enable = true; systemd.enable = true;
style = '' settings.mainBar = lib.mkMerge [
.modules-right { {
margin-right: 8px;
}
#custom-dnd {
margin-right: 8px;
}
'';
settings.mainBar = {
layer = "top"; layer = "top";
position = "top"; position = "top";
height = 30; height = 30;
spacing = 8; spacing = 8;
margin-right = 8;
modules-left = [ "hyprland/workspaces" ]; modules-left = moduleNames "left";
modules-center = [ "clock" ]; modules-center = moduleNames "center";
modules-right = [ modules-right = moduleNames "right";
"custom/recording" }
"custom/idle-lock" (lib.mapAttrs (_name: module: module.settings) modules)
"mpris"
"wireplumber"
]
++ lib.optional vpnClient.enable "custom/vpn"
++ [
"custom/network"
"battery"
"custom/dnd"
]; ];
# Per-application icons for the windows on each workspace, mapped from
# window class with a neutral glyph for anything unlisted.
"hyprland/workspaces" = {
on-click = "activate";
format = "{id} {windows}";
format-window-separator = " ";
window-rewrite-default = g "f2d0";
window-rewrite = {
"class<com.mitchellh.ghostty>" = g "f120";
"class<.*[Ff]irefox.*>" = g "f269";
"class<chromium.*>" = g "f268";
"class<[Cc]ode>" = g "f121";
"class<obsidian>" = g "f02d";
"class<[Ss]ignal>" = g "f4ad";
"class<[Ss]team>" = g "f1b6";
"class<[Vv]esktop>" = g "f1ff";
};
}; };
registry.waybar.${config.networking.hostName} = {
clock = { clock = {
position = "center";
order = 10;
settings = {
format = "{:%a %d %b %H:%M}"; format = "{:%a %d %b %H:%M}";
tooltip-format = "<tt>{calendar}</tt>"; tooltip-format = "<tt>{calendar}</tt>";
calendar = { calendar = {
@@ -172,77 +65,6 @@ in
format.today = "<b><u>{}</u></b>"; format.today = "<b><u>{}</u></b>";
}; };
}; };
mpris = {
format = "${g "f001"} {title}";
format-paused = "${g "f04c"} {title}";
max-length = 40;
on-click = "play-pause";
on-scroll-up = "next";
on-scroll-down = "previous";
};
wireplumber = {
format = "{icon} {volume}%";
format-muted = "${g "f026"} muted";
format-icons = [
(g "f026")
(g "f027")
(g "f028")
];
on-click = "${pkgs.wireplumber}/bin/wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle";
};
"custom/vpn" = {
return-type = "json";
exec = "${vpnStatus}";
interval = 5;
};
"custom/network" = {
return-type = "json";
exec = "${networkStatus}";
interval = 5;
};
battery = {
format = "{icon} {capacity}%";
format-charging = "${g "f0e7"} {capacity}%";
format-icons = [
(g "f244")
(g "f243")
(g "f242")
(g "f241")
(g "f240")
];
states = {
warning = 20;
critical = 10;
};
};
"custom/dnd" = {
return-type = "json";
exec = "${dndStatus}";
on-click = "${dndToggle}";
interval = "once";
signal = 8;
};
# Recording state has no event to hook, so the widget samples the
# wf-recorder process once a second.
"custom/recording" = {
return-type = "json";
exec = "${recStatus}";
interval = 1;
};
"custom/idle-lock" = {
return-type = "json";
exec = "${idleLockStatus}";
interval = "once";
signal = 9;
};
}; };
}; };
}; };
@@ -1,5 +1,30 @@
{ config, lib, ... }: {
config,
lib,
pkgs,
util,
...
}:
# PipeWire as the desktop audio server. # PipeWire as the desktop audio server.
let
volumeKey = keys: command: {
inherit keys;
repeating = true;
action = {
kind = "exec";
command = "${lib.getExe' pkgs.swayosd "swayosd-client"} --output-volume ${command}";
};
};
mediaKey = keys: command: {
inherit keys;
locked = true;
action = {
kind = "exec";
command = "${lib.getExe pkgs.playerctl} ${command}";
};
};
in
{ {
options.modules.desktop.utilities.audio.enable = lib.mkEnableOption "the PipeWire audio server"; options.modules.desktop.utilities.audio.enable = lib.mkEnableOption "the PipeWire audio server";
@@ -12,5 +37,50 @@
alsa.enable = true; alsa.enable = true;
pulse.enable = true; pulse.enable = true;
}; };
registry.keybind.${config.networking.hostName} = {
volume-up = volumeKey "XF86AudioRaiseVolume" "raise --max-volume 100";
volume-down = volumeKey "XF86AudioLowerVolume" "lower";
mute = {
keys = "XF86AudioMute";
locked = true;
action = {
kind = "exec";
command = "${lib.getExe' pkgs.swayosd "swayosd-client"} --output-volume mute-toggle";
};
};
media-play = mediaKey "XF86AudioPlay" "play-pause";
media-next = mediaKey "XF86AudioNext" "next";
media-previous = mediaKey "XF86AudioPrev" "previous";
};
registry.waybar.${config.networking.hostName} = {
mpris = {
order = 30;
settings = {
format = "${util.glyph "f001"} {title}";
format-paused = "${util.glyph "f04c"} {title}";
max-length = 40;
on-click = "play-pause";
on-scroll-up = "next";
on-scroll-down = "previous";
};
};
wireplumber = {
order = 40;
settings = {
format = "{icon} {volume}%";
format-muted = "${util.glyph "f026"} muted";
format-icons = [
(util.glyph "f026")
(util.glyph "f027")
(util.glyph "f028")
];
on-click = "${lib.getExe' pkgs.wireplumber "wpctl"} set-mute @DEFAULT_AUDIO_SINK@ toggle";
};
};
};
}; };
} }
@@ -6,21 +6,15 @@
}: }:
# Clipboard history: cliphist records every copy, picked back through rofi. # Clipboard history: cliphist records every copy, picked back through rofi.
let let
user = config.user.name;
cliphist = "${pkgs.cliphist}/bin/cliphist";
rofi = "${pkgs.rofi}/bin/rofi";
wl-copy = "${pkgs.wl-clipboard}/bin/wl-copy";
# The picker reuses the themed rofi, so history looks like every other menu # The picker reuses the themed rofi, so history looks like every other menu
# the launcher drives. # the launcher drives.
# decode is needed because list emits id-prefixed lines rather than the copied # decode is needed because list emits id-prefixed lines rather than the copied
# bytes, so the chosen id has to be resolved back before it can be re-copied. # bytes, so the chosen id has to be resolved back before it can be re-copied.
picker = pkgs.writeShellScript "clipboard-picker" '' picker = pkgs.writeShellScript "clipboard-picker" ''
${cliphist} list \ ${lib.getExe pkgs.cliphist} list \
| ${rofi} -dmenu -i -p Clipboard \ | ${lib.getExe pkgs.rofi} -dmenu -i -p Clipboard \
| ${cliphist} decode \ | ${lib.getExe pkgs.cliphist} decode \
| ${wl-copy} | ${lib.getExe' pkgs.wl-clipboard "wl-copy"}
''; '';
in in
{ {
@@ -28,7 +22,7 @@ in
lib.mkEnableOption "cliphist clipboard history"; lib.mkEnableOption "cliphist clipboard history";
config = lib.mkIf config.modules.desktop.utilities.clipboard.enable { config = lib.mkIf config.modules.desktop.utilities.clipboard.enable {
home-manager.users.${user} = { home-manager.users.${config.user.name} = {
# wl-copy and wl-paste on PATH, so the shell can pipe into and out of the # wl-copy and wl-paste on PATH, so the shell can pipe into and out of the
# clipboard. # clipboard.
# The watchers and picker above reach wl-clipboard by store path, so this # The watchers and picker above reach wl-clipboard by store path, so this
@@ -38,13 +32,14 @@ in
# Two watchers record text and images to history, bound to the graphical # Two watchers record text and images to history, bound to the graphical
# session so uwsm starts and stops them with it. # session so uwsm starts and stops them with it.
services.cliphist.enable = true; services.cliphist.enable = true;
};
# $mod is defined by the compositor config these binds share. registry.keybind.${config.networking.hostName}.clipboard-history = {
/* keys = "SUPER + SHIFT + V";
wayland.windowManager.hyprland.settings.bind = [ action = {
"$mod SHIFT, V, exec, ${picker}" kind = "exec";
]; command = "${picker}";
*/ };
}; };
}; };
} }
@@ -5,9 +5,6 @@
... ...
}: }:
# SwayOSD: a transient on-screen popup for volume and brightness changes. # SwayOSD: a transient on-screen popup for volume and brightness changes.
let
user = config.user.name;
in
{ {
options.modules.desktop.utilities.osd.enable = options.modules.desktop.utilities.osd.enable =
lib.mkEnableOption "the SwayOSD volume and brightness popup"; lib.mkEnableOption "the SwayOSD volume and brightness popup";
@@ -19,21 +16,41 @@ in
# group write, so the server dims the panel without root. # group write, so the server dims the panel without root.
# Membership below grants the running session that access. # Membership below grants the running session that access.
services.udev.packages = [ pkgs.swayosd ]; services.udev.packages = [ pkgs.swayosd ];
users.users.${user}.extraGroups = [ "video" ]; users.users.${config.user.name}.extraGroups = [ "video" ];
# The server draws the popups, so it runs for the whole graphical session. # The server draws the popups, so it runs for the whole graphical session.
# It binds to the target uwsm activates. # It binds to the target uwsm activates.
home-manager.users.${user}.systemd.user.services.swayosd = { home-manager.users.${config.user.name}.systemd.user.services.swayosd = {
Unit = { Unit = {
Description = "SwayOSD on-screen display server"; Description = "SwayOSD on-screen display server";
PartOf = [ "graphical-session.target" ]; PartOf = [ "graphical-session.target" ];
After = [ "graphical-session.target" ]; After = [ "graphical-session.target" ];
}; };
Service = { Service = {
ExecStart = "${pkgs.swayosd}/bin/swayosd-server"; ExecStart = lib.getExe' pkgs.swayosd "swayosd-server";
Restart = "on-failure"; Restart = "on-failure";
}; };
Install.WantedBy = [ "graphical-session.target" ]; Install.WantedBy = [ "graphical-session.target" ];
}; };
registry.keybind.${config.networking.hostName} = {
brightness-up = {
keys = "XF86MonBrightnessUp";
repeating = true;
action = {
kind = "exec";
command = "${lib.getExe' pkgs.swayosd "swayosd-client"} --brightness raise";
};
};
brightness-down = {
keys = "XF86MonBrightnessDown";
repeating = true;
action = {
kind = "exec";
command = "${lib.getExe' pkgs.swayosd "swayosd-client"} --brightness lower";
};
};
};
}; };
} }
@@ -2,41 +2,44 @@
config, config,
lib, lib,
pkgs, pkgs,
util,
... ...
}: }:
# Keybound screen recording: pick a region, then toggle a video-only capture. # Keybound screen recording: pick a region, then toggle a video-only capture.
let let
user = config.user.name; # A single key starts and stops recording.
# Waybar refreshes on state changes instead of polling.
recordingToggle = pkgs.writeShellScript "screen-record-toggle" ''
refresh_waybar() {
${lib.getExe' pkgs.procps "pkill"} -RTMIN+10 waybar >/dev/null 2>&1 || true
}
slurp = "${pkgs.slurp}/bin/slurp"; if ${lib.getExe' pkgs.procps "pgrep"} -x wf-recorder >/dev/null; then
wf-recorder = "${pkgs.wf-recorder}/bin/wf-recorder"; ${lib.getExe' pkgs.procps "pkill"} -INT -x wf-recorder
notify-send = "${pkgs.libnotify}/bin/notify-send";
pgrep = "${pkgs.procps}/bin/pgrep";
pkill = "${pkgs.procps}/bin/pkill";
date = "${pkgs.coreutils}/bin/date";
mkdir = "${pkgs.coreutils}/bin/mkdir";
xdgUserDir = "${pkgs.xdg-user-dirs}/bin/xdg-user-dir";
# A single key both starts and stops.
# A running wf-recorder is stopped with SIGINT so it finalises the file.
# Otherwise slurp picks a region and wf-recorder runs in the foreground until
# that stop arrives, so this instance lives for the whole recording and then
# reports it saved.
# No -a means no audio is captured.
toggle = pkgs.writeShellScript "screen-record-toggle" ''
if ${pgrep} -x wf-recorder >/dev/null; then
${pkill} -INT -x wf-recorder
exit 0 exit 0
fi fi
region=$(${slurp}) || exit 0 region=$(${lib.getExe pkgs.slurp}) || exit 0
dir="$(${xdgUserDir} VIDEOS)/Recordings" dir="$(${lib.getExe' pkgs.xdg-user-dirs "xdg-user-dir"} VIDEOS)/Recordings"
${mkdir} -p "$dir" ${lib.getExe' pkgs.coreutils "mkdir"} -p "$dir"
file="$dir/recording-$(${date} +%Y%m%d-%H%M%S).mp4" file="$dir/recording-$(${lib.getExe' pkgs.coreutils "date"} +%Y%m%d-%H%M%S).mp4"
${notify-send} -a "Screen recording" "Recording started" "Region capture, no audio." ${lib.getExe' pkgs.libnotify "notify-send"} -a "Screen recording" "Recording started" "Region capture, no audio."
${wf-recorder} -g "$region" -f "$file" ${lib.getExe pkgs.wf-recorder} -g "$region" -f "$file" &
${notify-send} -a "Screen recording" "Recording saved" "$file" recorder=$!
refresh_waybar
wait "$recorder" || true
refresh_waybar
${lib.getExe' pkgs.libnotify "notify-send"} -a "Screen recording" "Recording saved" "$file"
'';
# Empty text collapses the widget when recording is idle.
recordingStatus = pkgs.writeShellScript "waybar-recording-status" ''
if ${lib.getExe' pkgs.procps "pgrep"} -x wf-recorder >/dev/null; then
printf '{"text":"${util.glyph "f03d"}","tooltip":"Recording","class":"recording"}\n'
else
printf '{"text":"","class":"idle"}\n'
fi
''; '';
in in
{ {
@@ -44,13 +47,22 @@ in
lib.mkEnableOption "wf-recorder screen recording"; lib.mkEnableOption "wf-recorder screen recording";
config = lib.mkIf config.modules.desktop.utilities.recording.enable { config = lib.mkIf config.modules.desktop.utilities.recording.enable {
home-manager.users.${user} = { registry.keybind.${config.networking.hostName}.recording-toggle = {
# $mod is defined by the compositor config these binds share. keys = "SUPER + SHIFT + R";
/* action = {
wayland.windowManager.hyprland.settings.bind = [ kind = "exec";
"$mod SHIFT, R, exec, ${toggle}" command = "${recordingToggle}";
]; };
*/ };
registry.waybar.${config.networking.hostName}."custom/recording" = {
order = 10;
settings = {
return-type = "json";
exec = "${recordingStatus}";
interval = "once";
signal = 10;
};
}; };
}; };
} }
@@ -7,26 +7,26 @@
# Keyboard-driven screenshots copy to the clipboard before Satty opens for # Keyboard-driven screenshots copy to the clipboard before Satty opens for
# annotation. Satty copies annotated screenshots when it saves them. # annotation. Satty copies annotated screenshots when it saves them.
let let
user = config.user.name; screenshotKey = keys: target: {
inherit keys;
grimblast = "${pkgs.grimblast}/bin/grimblast"; action = {
satty = "${pkgs.satty}/bin/satty"; kind = "exec";
tee = "${pkgs.coreutils}/bin/tee"; command = "${capture target}";
wl-copy = "${pkgs.wl-clipboard}/bin/wl-copy"; };
xdgUserDir = "${pkgs.xdg-user-dirs}/bin/xdg-user-dir"; };
# Copy the original screenshot before Satty opens. # Copy the original screenshot before Satty opens.
# Satty copies and saves annotated screenshots when the user presses Enter. # Satty copies and saves annotated screenshots when the user presses Enter.
capture = capture =
target: target:
pkgs.writeShellScript "screenshot-${target}" '' pkgs.writeShellScript "screenshot-${target}" ''
dir="$(${xdgUserDir} PICTURES)/Screenshots" dir="$(${lib.getExe' pkgs.xdg-user-dirs "xdg-user-dir"} PICTURES)/Screenshots"
mkdir -p "$dir" ${lib.getExe' pkgs.coreutils "mkdir"} -p "$dir"
${grimblast} save ${target} - \ ${lib.getExe pkgs.grimblast} save ${target} - \
| ${tee} >(${wl-copy}) \ | ${lib.getExe' pkgs.coreutils "tee"} >(${lib.getExe' pkgs.wl-clipboard "wl-copy"}) \
| ${satty} --filename - \ | ${lib.getExe pkgs.satty} --filename - \
--output-filename "$dir/screenshot-%Y%m%d-%H%M%S.png" \ --output-filename "$dir/screenshot-%Y%m%d-%H%M%S.png" \
--copy-command ${wl-copy} \ --copy-command ${lib.getExe' pkgs.wl-clipboard "wl-copy"} \
--save-after-copy \ --save-after-copy \
--early-exit \ --early-exit \
--actions-on-enter save-to-clipboard --actions-on-enter save-to-clipboard
@@ -37,27 +37,21 @@ in
lib.mkEnableOption "screenshots via grimblast and satty"; lib.mkEnableOption "screenshots via grimblast and satty";
config = lib.mkIf config.modules.desktop.utilities.screenshot.enable { config = lib.mkIf config.modules.desktop.utilities.screenshot.enable {
home-manager.users.${user} = { home-manager.users.${config.user.name} = {
# satty is a one-shot annotation surface, so float it rather than letting # satty is a one-shot annotation surface, so float it rather than letting
# it claim a tile in the layout. # it claim a tile in the layout.
# windowrule v3 syntax: space-separated field/value tokens, comma wayland.windowManager.hyprland.settings.window_rule = [
# separated, with matchers under a match: prefix and effects bare. {
/* match.class = "^(com\\.gabm\\.satty)$";
wayland.windowManager.hyprland.settings.windowrule = [ float = true;
"float 1, match:class ^(com\\.gabm\\.satty)$" }
]; ];
*/ };
# Print with plain/Shift/Ctrl for region/window/full. registry.keybind.${config.networking.hostName} = {
# Super+L is already the hjkl focus and movement bind, so screenshots take screenshot-area = screenshotKey "Print" "area";
# the Print key instead. screenshot-active = screenshotKey "SHIFT + Print" "active";
/* screenshot-screen = screenshotKey "CTRL + Print" "screen";
wayland.windowManager.hyprland.settings.bind = [
", Print, exec, ${capture "area"}"
"SHIFT, Print, exec, ${capture "active"}"
"CTRL, Print, exec, ${capture "screen"}"
];
*/
}; };
}; };
} }
@@ -6,15 +6,13 @@
}: }:
# Nord theming for the graphical layer, driven from one base16 scheme by Stylix. # Nord theming for the graphical layer, driven from one base16 scheme by Stylix.
let let
# A single static Nord wallpaper, drawn as a vertical gradient across the # A single static Nord wallpaper, drawn as a vertical gradient across the
# Polar Night shades so it needs no committed binary and no network fetch. # Polar Night shades so it needs no committed binary and no network fetch.
wallpaper = pkgs.runCommand "nord-wallpaper.png" { } '' wallpaper = pkgs.runCommand "nord-wallpaper.png" { } ''
${pkgs.imagemagick}/bin/magick \ ${lib.getExe pkgs.imagemagick} \
-size 2560x1440 gradient:'#2E3440'-'#3B4252' \ -size 2560x1440 gradient:'#2E3440'-'#3B4252' \
"$out" "$out"
''; '';
user = config.user.name;
in in
{ {
options.modules.desktop.utilities.theming.enable = options.modules.desktop.utilities.theming.enable =
@@ -59,7 +57,7 @@ in
}; };
}; };
home-manager.users.${user} = { home-manager.users.${config.user.name} = {
# Stylix drives the cursor through home-manager's pointer-cursor config, # Stylix drives the cursor through home-manager's pointer-cursor config,
# whose generation must be switched on explicitly. # whose generation must be switched on explicitly.
home.pointerCursor.enable = true; home.pointerCursor.enable = true;
@@ -68,5 +66,10 @@ in
# base16 mapping Stylix would apply, so its target stays off. # base16 mapping Stylix would apply, so its target stays off.
stylix.targets.nixvim.enable = false; stylix.targets.nixvim.enable = false;
}; };
registry.env.${config.networking.hostName} = {
HYPRCURSOR_THEME = config.stylix.cursor.name;
HYPRCURSOR_SIZE = toString config.stylix.cursor.size;
};
}; };
} }
@@ -1,14 +1,27 @@
{ config, lib, ... }: { config, lib, ... }:
# Declares the XDG user directories, so a tool that queries them lands in a # Declares XDG user directories, so tools that query them use predictable
# well-known folder a host can relocate from one place. # folders a host can relocate from one place.
let let
user = config.user.name; homeDirectory = "/home/${config.user.name}";
in in
{ {
options.modules.desktop.utilities.userdirs.enable = lib.mkEnableOption "XDG user directories"; options.modules.desktop.utilities.userdirs.enable = lib.mkEnableOption "XDG user directories";
config = lib.mkIf config.modules.desktop.utilities.userdirs.enable { config = lib.mkIf config.modules.desktop.utilities.userdirs.enable {
# Write ~/.config/user-dirs.dirs from the option defaults. home-manager.users.${config.user.name}.xdg.userDirs = {
home-manager.users.${user}.xdg.userDirs.enable = true; enable = true;
createDirectories = true;
setSessionVariables = true;
desktop = "${homeDirectory}/.ignoreme";
documents = "${homeDirectory}/docs";
download = "${homeDirectory}/dwn";
music = "${homeDirectory}/mus";
pictures = "${homeDirectory}/pic";
publicShare = "${homeDirectory}/.ignoreme";
templates = "${homeDirectory}/.ignoreme";
videos = "${homeDirectory}/vid";
projects = "${homeDirectory}/.ignoreme";
};
}; };
} }
+1
View File
@@ -53,6 +53,7 @@ in
home.username = config.user.name; home.username = config.user.name;
home.homeDirectory = "/home/${config.user.name}"; home.homeDirectory = "/home/${config.user.name}";
home.stateVersion = config.system.stateVersion; home.stateVersion = config.system.stateVersion;
home.sessionVariables = lib.attrByPath [ config.networking.hostName ] { } config.registry.env;
home.packages = with pkgs; [ home.packages = with pkgs; [
eza eza
unzip unzip
+1 -1
View File
@@ -5,7 +5,7 @@
}: }:
# Imports existing ZFS pools that hold durable service state. # Imports existing ZFS pools that hold durable service state.
let let
cfg = config.modules.host.zfs; # NOLINT(let_order) cfg = config.modules.host.zfs;
in in
{ {
options.modules.host.zfs = { options.modules.host.zfs = {
+57
View File
@@ -0,0 +1,57 @@
{
config,
lib,
pkgs,
util,
...
}:
# NetworkManager-managed networking.
let
networkStatus = pkgs.writeShellScript "waybar-network-status" ''
active=$(
${lib.getExe' pkgs.networkmanager "nmcli"} -t -f DEVICE,TYPE,STATE,CONNECTION device status \
| ${lib.getExe' pkgs.gawk "awk"} -F: '$3 == "connected" && $2 != "loopback" { print; exit }'
)
if [ -z "$active" ]; then
${lib.getExe pkgs.jq} -cn \
--arg text "${util.glyph "f127"} off" \
--arg tooltip "Network disconnected" \
--arg class "disconnected" \
'{ text: $text, tooltip: $tooltip, class: $class }'
exit 0
fi
IFS=: read -r device type _state connection <<< "$active"
case "$type" in
wifi) icon="${util.glyph "f1eb"}" ;;
ethernet) icon="LAN" ;;
*) icon="NET" ;;
esac
ipaddr=$(${lib.getExe' pkgs.iproute2 "ip"} -4 -o addr show dev "$device" | ${lib.getExe' pkgs.gawk "awk"} '{ print $4; exit }')
${lib.getExe pkgs.jq} -cn \
--arg text "$icon $connection" \
--arg tooltip "$device: ''${ipaddr:-no IPv4}" \
--arg class "$type" \
'{ text: $text, tooltip: $tooltip, class: $class }'
'';
in
{
options.modules.network.enable = lib.mkEnableOption "NetworkManager-managed networking";
config = lib.mkIf config.modules.network.enable {
networking.networkmanager.enable = true;
registry.waybar.${config.networking.hostName}."custom/network" = {
order = 60;
settings = {
return-type = "json";
exec = "${networkStatus}";
interval = 5;
};
};
};
}
+15 -13
View File
@@ -7,19 +7,17 @@
# Configures inbound and outbound SSH access. # Configures inbound and outbound SSH access.
let let
cfg = config.modules.network.ssh; cfg = config.modules.network.ssh;
user = config.user.name; # NOLINT(let_order) user = config.user.name;
# NOLINT(let_order)
workstationNames = [ workstationNames = [
"neogaia" "neogaia"
"zeus" "zeus"
]; ];
serverNames = [ "pikachu" ]; serverNames = [ "pikachu" ];
isWorkstation = lib.elem config.networking.hostName workstationNames; # NOLINT(let_order) isWorkstation = lib.elem config.networking.hostName workstationNames;
isServer = lib.elem config.networking.hostName serverNames; # NOLINT(let_order) isServer = lib.elem config.networking.hostName serverNames;
# NOLINT(let_order)
clientKeyFor = host: builtins.readFile (../../hosts + "/${host}/ssh_user_ed25519_key.pub"); clientKeyFor = host: builtins.readFile (../../hosts + "/${host}/ssh_user_ed25519_key.pub");
hostKeysFor = hostKeysFor =
host: host:
@@ -28,7 +26,6 @@ let
(../../hosts + "/${host}/ssh_host_rsa_key.pub") (../../hosts + "/${host}/ssh_host_rsa_key.pub")
]; ];
# NOLINT(let_order)
managedTargets = lib.genAttrs (workstationNames ++ serverNames) (name: { managedTargets = lib.genAttrs (workstationNames ++ serverNames) (name: {
hostName = registry.address.${name}.self; hostName = registry.address.${name}.self;
clientKey = clientKeyFor name; clientKey = clientKeyFor name;
@@ -36,19 +33,25 @@ let
}); });
extraTargets = { extraTargets = {
# TODO: Pin Gitea's host key after migrating it from Proxmox.
gitea = { gitea = {
hostName = "git.alexion.dev"; hostName = "git.alexion.dev";
port = 2022;
user = "gitea"; user = "gitea";
hostKeys = [
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFcUl17AcZz1wS8ek2yS/bu5NRTX4ViYTuFOSnp8leHmirP3Zk5QlC33hodQp09J6EA6Vl8zUowy4qLud7BMurQ="
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICkK2W2Ev+9RXa2PNXiNPPCPF5ln2+M2jHiGoZ4cPYxX"
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDZSeU1iRHoaIXgbYe0kAiOAASw9LrQhu54RNCoTQ2O1rbqgnnKO2qbYJvfmUWL7jqEkEotgUBy4Xqxgfl7rXGQ9viWZe+i2tKwJdGsabNLJ+QTDCNyGCd22s1Hhl7n68JvuLTENXl4WpH56MB3yjFmK9onLHHcLG+rWiR0I6Yn264LfNVX0RuZK7TlG0tUKJR5bQBXGT6PxAE1IceYRgbgM0BYq4nakNg/s4ZSpmJFrrGfCHNsnHiEmFAXRFrGwf+0ef2STDukM/ADLziPXu0Ge7k72/UPvtEdcpgvzIDMJ2EznKTnxIoZnFkrDqhGOo8DnXK+cFVKAkkC6NgWQpO6fNnY+MEDgSb0fr/rGcwzUa1p+fON5/zEYxsAtKyAeP4D7OEAo65lsSKqi1tbt521miTobp0NOT8p4tGgHTwmshbqlmUZz0DVexN6uc7yzoHu4V/oYomEWP/j/E2uuvLi57AaJbM3Z/oAHUtrHFK9A9FFggyzpETZE7qWA9BhO/pJQUsjdWRm0pUHsPlf9Uqqit2BKVERiMSlHsBKch4tIk4ryZBazWunDD+QFcllKG74nMVISZ7i8q9IfNy+PWQuJIEm5XrT9W5pnkBIWrePlcAcPo080ALigmyhH+WOPiyO+dfueeq6PVdu2Voc+6FvtylRcn4u8O+E5Wq5amvQAQ=="
];
aliases = [ aliases = [
"gitea" "gitea"
"git.alexion.dev" "git.alexion.dev"
]; ];
}; };
steammachine = {
hostName = "10.23.50.234";
user = "deck";
};
}; };
# NOLINT(let_order)
mkTarget = name: target: { mkTarget = name: target: {
hostName = target.hostName or name; hostName = target.hostName or name;
user = target.user or user; user = target.user or user;
@@ -57,15 +60,14 @@ let
clientKey = target.clientKey or null; clientKey = target.clientKey or null;
hostKeys = target.hostKeys or [ ]; hostKeys = target.hostKeys or [ ];
}; };
targets = lib.mapAttrs mkTarget (managedTargets // extraTargets); # NOLINT(let_order) targets = lib.mapAttrs mkTarget (managedTargets // extraTargets);
clientKeysFor = names: lib.filter (key: key != null) (map (name: targets.${name}.clientKey) names); # NOLINT(let_order) clientKeysFor = names: lib.filter (key: key != null) (map (name: targets.${name}.clientKey) names);
# NOLINT(let_order)
defaultAuthorizedKeys = lib.flatten ( defaultAuthorizedKeys = lib.flatten (
clientKeysFor workstationNames ++ lib.optional isServer (clientKeysFor serverNames) clientKeysFor workstationNames ++ lib.optional isServer (clientKeysFor serverNames)
); );
outboundTargetNames = # NOLINT(let_order) outboundTargetNames =
let let
groupTargets = groupTargets =
if isServer then if isServer then
+1 -1
View File
@@ -6,7 +6,7 @@
}: }:
# Configures bridges for tagged VLANs on a physical interface that uses DHCP. # Configures bridges for tagged VLANs on a physical interface that uses DHCP.
let let
cfg = config.modules.network.vlans; # NOLINT(let_order) cfg = config.modules.network.vlans;
in in
{ {
options.modules.network.vlans = { options.modules.network.vlans = {
+34 -1
View File
@@ -1,10 +1,34 @@
{ {
config, config,
lib, lib,
pkgs,
util,
... ...
}: }:
let let
cfg = config.modules.network.vpn-client; # NOLINT(let_order) cfg = config.modules.network.vpn-client;
vpnIcon = util.glyph [
"db83"
"dc9d"
];
vpnStatus = pkgs.writeShellScript "waybar-vpn-status" ''
interface=${lib.escapeShellArg cfg.interface}
if ! ${lib.getExe' pkgs.iproute2 "ip"} link show dev "$interface" >/dev/null 2>&1; then
printf '{"text":"","class":"idle"}\n'
exit 0
fi
ipaddr=$(${lib.getExe' pkgs.iproute2 "ip"} -4 -o addr show dev "$interface" | ${lib.getExe' pkgs.gawk "awk"} '{ print $4; exit }')
${lib.getExe pkgs.jq} -cn \
--arg text "${vpnIcon}" \
--arg tooltip "VPN $interface: ''${ipaddr:-no IPv4}" \
--arg class "active" \
'{ text: $text, tooltip: $tooltip, class: $class }'
'';
in in
{ {
options.modules.network.vpn-client = { options.modules.network.vpn-client = {
@@ -57,6 +81,15 @@ in
vpn-off = "sudo systemctl stop 'wireguard-${cfg.interface}*.service' wireguard-${cfg.interface}.target"; vpn-off = "sudo systemctl stop 'wireguard-${cfg.interface}*.service' wireguard-${cfg.interface}.target";
}; };
registry.waybar.${config.networking.hostName}."custom/vpn" = {
order = 50;
settings = {
return-type = "json";
exec = "${vpnStatus}";
interval = 5;
};
};
systemd.targets."wireguard-${cfg.interface}".wantedBy = lib.mkForce [ ]; systemd.targets."wireguard-${cfg.interface}".wantedBy = lib.mkForce [ ];
networking.wireguard.interfaces.${cfg.interface} = { networking.wireguard.interfaces.${cfg.interface} = {
@@ -1,62 +0,0 @@
{
config,
lib,
...
}:
let
cfg = config.modules.services.actualbudget; # NOLINT(let_order)
in
{
options.modules.services.actualbudget = {
enable = lib.mkEnableOption "Actual Budget";
port = lib.mkOption {
type = lib.types.port;
default = 5006;
description = "Port Actual Budget listens on.";
};
dataDir = lib.mkOption {
type = lib.types.str;
default = "/data";
description = "Directory where Actual Budget stores server and user files.";
};
user = lib.mkOption {
type = lib.types.str;
default = "actual";
description = "User account that runs Actual Budget.";
};
group = lib.mkOption {
type = lib.types.str;
default = "storage";
description = "Group account that owns Actual Budget's writable state.";
};
};
config = lib.mkMerge [
{
registry."stable-uid".${config.networking.hostName}.actualbudget = 20001;
}
(lib.mkIf cfg.enable {
users.users.${cfg.user} = {
isSystemUser = true;
uid = config.registry."stable-uid".${config.networking.hostName}.actualbudget;
inherit (cfg) group;
};
services.actual = {
enable = true;
openFirewall = true;
inherit (cfg) user;
inherit (cfg) group;
settings = {
inherit (cfg) port dataDir;
};
};
})
];
}
@@ -0,0 +1,274 @@
{ config, lib, ... }:
let
cfg = config.modules.services.adguardhome;
in
{
options.modules.services.adguardhome = {
enable = lib.mkEnableOption "AdGuard Home";
adminPasswordHash = lib.mkOption {
type = lib.types.str;
description = "Bcrypt verifier for the AdGuard Home administrator password.";
};
reverseProxyAddress = lib.mkOption {
type = lib.types.str;
description = "IP address of the guest that handles internal HTTP requests.";
};
};
config = lib.mkIf cfg.enable {
services.adguardhome = {
enable = true;
mutableSettings = false;
openFirewall = true;
settings = {
http = {
pprof = {
port = 6060;
enabled = false;
};
address = "0.0.0.0:80";
session_ttl = "720h";
};
users = [
{
name = config.user.name;
password = cfg.adminPasswordHash;
}
];
auth_attempts = 5;
block_auth_min = 15;
http_proxy = "";
language = "";
theme = "auto";
dns = {
bind_hosts = [ "0.0.0.0" ];
port = 53;
anonymize_client_ip = false;
ratelimit = 0;
refuse_any = true;
upstream_dns = [
"https://dns.cloudflare.com/dns-query"
"tls://1.1.1.1"
"https://dns.google/dns-query"
"tls://8.8.8.8"
"https://dns10.quad9.net/dns-query"
"tls://9.9.9.9"
];
upstream_dns_file = "";
bootstrap_dns = [
"9.9.9.10"
"149.112.112.10"
"2620:fe::10"
"2620:fe::fe:10"
];
fallback_dns = [ ];
upstream_mode = "parallel";
fastest_timeout = "1s";
allowed_clients = [ ];
disallowed_clients = [ ];
blocked_hosts = [
"version.bind"
"id.server"
"hostname.bind"
];
trusted_proxies = [
"127.0.0.0/8"
"::1/128"
];
cache_enabled = true;
cache_size = 4194304;
cache_ttl_min = 0;
cache_ttl_max = 0;
cache_optimistic = false;
cache_optimistic_answer_ttl = "30s";
cache_optimistic_max_age = "12h";
bogus_nxdomain = [ ];
aaaa_disabled = false;
enable_dnssec = false;
edns_client_subnet = {
custom_ip = "";
enabled = false;
use_custom = false;
};
max_goroutines = 300;
handle_ddr = true;
ipset = [ ];
ipset_file = "";
bootstrap_prefer_ipv6 = false;
upstream_timeout = "10s";
private_networks = [ ];
use_private_ptr_resolvers = true;
local_ptr_upstreams = [ ];
use_dns64 = false;
dns64_prefixes = [ ];
serve_http3 = false;
use_http3_upstreams = false;
serve_plain_dns = true;
hostsfile_enabled = true;
pending_requests.enabled = true;
};
tls = {
enabled = false;
server_name = "";
force_https = false;
port_https = 443;
port_dns_over_tls = 853;
port_dns_over_quic = 853;
port_dnscrypt = 0;
dnscrypt_config_file = "";
allow_unencrypted_doh = false;
certificate_chain = "";
private_key = "";
certificate_path = "";
private_key_path = "";
strict_sni_check = false;
};
querylog = {
dir_path = "";
ignored = [ ];
interval = "2160h";
size_memory = 1000;
enabled = true;
ignored_enabled = false;
file_enabled = true;
};
statistics = {
dir_path = "";
ignored = [ ];
interval = "24h";
enabled = true;
ignored_enabled = false;
};
filters = [
{
enabled = true;
url = "https://adguardteam.github.io/HostlistsRegistry/assets/filter_1.txt";
name = "AdGuard DNS filter";
id = 1;
}
{
enabled = false;
url = "https://adguardteam.github.io/HostlistsRegistry/assets/filter_2.txt";
name = "AdAway Default Blocklist";
id = 2;
}
];
whitelist_filters = [ ];
user_rules = [ ];
dhcp = {
enabled = false;
interface_name = "";
local_domain_name = "lan";
dhcpv4 = {
gateway_ip = "";
subnet_mask = "";
range_start = "";
range_end = "";
lease_duration = 86400;
icmp_timeout_msec = 1000;
options = [ ];
};
dhcpv6 = {
range_start = "";
lease_duration = 86400;
ra_slaac_only = false;
ra_allow_slaac = false;
};
};
filtering = {
blocking_ipv4 = "";
blocking_ipv6 = "";
blocked_services = {
schedule.time_zone = "Local";
ids = [ ];
};
protection_disabled_until = null;
safe_search = {
enabled = false;
bing = true;
duckduckgo = true;
ecosia = true;
google = true;
pixabay = true;
yandex = true;
youtube = true;
};
blocking_mode = "default";
parental_block_host = "family-block.dns.adguard.com";
safebrowsing_block_host = "standard-block.dns.adguard.com";
rewrites = [
{
domain = "*.home";
answer = "10.23.20.32";
enabled = true;
}
{
domain = "*.alexion.dev";
answer = cfg.reverseProxyAddress;
enabled = true;
}
{
domain = "home";
answer = cfg.reverseProxyAddress;
enabled = true;
}
];
safe_fs_patterns = [ "/opt/AdGuardHome/userfilters/*" ];
safebrowsing_cache_size = 1048576;
safesearch_cache_size = 1048576;
parental_cache_size = 1048576;
cache_time = 30;
filters_update_interval = 24;
blocked_response_ttl = 10;
filtering_enabled = true;
rewrites_enabled = true;
parental_enabled = false;
safebrowsing_enabled = false;
protection_enabled = true;
};
clients = {
runtime_sources = {
whois = true;
arp = true;
rdns = true;
dhcp = true;
hosts = true;
};
persistent = [ ];
};
log = {
enabled = true;
file = "";
max_backups = 0;
max_size = 100;
max_age = 3;
compress = false;
local_time = false;
verbose = false;
};
os = {
group = "";
user = "";
rlimit_nofile = 0;
};
};
};
networking.firewall = {
allowedTCPPorts = [ 53 ];
allowedUDPPorts = [ 53 ];
};
};
}
+124 -133
View File
@@ -2,16 +2,105 @@
config, config,
lib, lib,
pkgs, pkgs,
util,
... ...
}: }:
let let
cfg = config.modules.services.copyparty; # NOLINT(let_order) cfg = config.modules.services.copyparty;
volumeType = lib.types.submodule { accountName = config.user.name;
serviceGroup = "storage";
serviceStateDir = "/var/lib/copyparty";
serviceUser = "copyparty";
writableVolumes = lib.filter (volume: !volume.readOnly) (lib.attrValues cfg.volumes);
port = 3923;
defaultAccess = {
A = [ accountName ];
};
defaultWritableFlags = {
d2d = true;
d2t = true;
dthumb = true;
};
credentialHash = builtins.substring 0 16 (builtins.hashString "sha256" accountName);
credentialName = "password-${credentialHash}";
passwordPlaceholder = "@COPYPARTY_PASSWORD_${credentialHash}@";
globalSettings = {
i = "0.0.0.0";
usernames = true;
"http-only" = true;
"no-crt" = true;
"no-thumb" = true;
"no-snap" = true;
"no-rescan" = true;
"ses-db" = "${serviceStateDir}/sessions.db";
"chpw-db" = "${serviceStateDir}/chpw.json";
"shr-db" = "${serviceStateDir}/shares.db";
}
// lib.optionalAttrs cfg.reverseProxy.enable {
rproxy = 1;
"xff-hdr" = "x-forwarded-for";
};
globalExtraConfig = lib.optionalString cfg.reverseProxy.enable (
lib.concatMapStringsSep "\n" (source: "xff-src: ${source}") cfg.reverseProxy.trustedSources
);
volumeFlags =
flags:
lib.optionalAttrs (flags != { }) (
{
chmod_d = "2770";
chmod_f = "660";
}
// flags
);
renderedVolumes = lib.mapAttrs (_urlPath: volume: {
inherit (volume) path;
access = if volume.readOnly then { r = [ accountName ]; } else defaultAccess // volume.access;
flags = volumeFlags (lib.optionalAttrs (!volume.readOnly) defaultWritableFlags // volume.flags);
}) cfg.volumes;
configText = util.formats.copyparty.render {
inherit globalExtraConfig;
accounts.${accountName} = passwordPlaceholder;
global = globalSettings;
volumes = renderedVolumes;
};
configFile = pkgs.writeText "copyparty.conf" configText;
replacePassword = ''
${lib.getExe pkgs.replace-secret} ${lib.escapeShellArg passwordPlaceholder} "$CREDENTIALS_DIRECTORY/${credentialName}" /run/copyparty/copyparty.conf
'';
in
{
options.modules.services.copyparty = {
enable = lib.mkEnableOption "Copyparty";
passwordFile = lib.mkOption {
type = lib.types.str;
description = "Sets the runtime file that contains the Copyparty account password.";
};
volumes = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule {
options = { options = {
path = lib.mkOption { path = lib.mkOption {
type = lib.types.str; type = lib.types.externalPath;
description = "Filesystem path served by this volume."; description = "Sets the filesystem path served by this volume.";
}; };
access = lib.mkOption { access = lib.mkOption {
@@ -20,129 +109,28 @@ let
example = { example = {
A = [ "alexion" ]; A = [ "alexion" ];
}; };
description = "Copyparty access map from permission string to account names."; description = "Maps Copyparty permission strings to account names.";
}; };
readOnly = lib.mkOption { readOnly = lib.mkOption {
type = lib.types.bool; type = lib.types.bool;
default = false; default = false;
description = "Serve this volume read-only."; description = "Serves this volume read-only.";
}; };
flags = lib.mkOption { flags = lib.mkOption {
type = lib.types.listOf lib.types.str; type = lib.types.attrs;
default = [ ];
example = [ "dthumb" ];
description = "Copyparty volume flags.";
};
};
};
configScript = pkgs.writeShellScript "copyparty-config" ''
set -eu
umask 077
password="$(${pkgs.coreutils}/bin/tr -d '\n' < "$CREDENTIALS_DIRECTORY/password")"
cat > /run/copyparty/copyparty.conf <<EOF
[global]
p: ${toString cfg.port}
usernames
http-only
no-crt
no-thumb
no-snap
no-rescan
ses-db: ${cfg.stateDir}/sessions.db
chpw-db: ${cfg.stateDir}/chpw.json
shr-db: ${cfg.stateDir}/shares.db
${renderedReverseProxy}
[accounts]
${cfg.accountName}: $password
${renderedVolumes}
EOF
'';
renderAccess = permission: accounts: " ${permission}: ${lib.concatStringsSep ", " accounts}";
hasFlag =
name: flags: lib.any (flag: lib.hasPrefix "${name}:" flag || lib.hasPrefix "${name}=" flag) flags;
defaultPermissionFlags =
flags:
lib.optionals (!(hasFlag "chmod_d" flags)) [ "chmod_d: 2770" ]
++ lib.optionals (!(hasFlag "chmod_f" flags)) [ "chmod_f: 660" ];
renderFlags =
flags: lib.concatMapStringsSep "\n" (flag: " ${flag}") (flags ++ defaultPermissionFlags flags);
renderVolume = urlPath: volume: ''
[${urlPath}]
${volume.path}
accs:
${lib.concatStringsSep "\n" (lib.mapAttrsToList renderAccess volume.access)}
${lib.optionalString (volume.flags != [ ]) ''
flags:
${renderFlags volume.flags}
''}
'';
renderTrustedSource = source: " xff-src: ${source}";
renderedReverseProxy = lib.optionalString cfg.reverseProxy.enable ''
rproxy: 1
xff-hdr: x-forwarded-for
${lib.concatStringsSep "\n" (map renderTrustedSource cfg.reverseProxy.trustedSources)}
'';
renderedVolumes = lib.concatStringsSep "\n" (lib.mapAttrsToList renderVolume cfg.volumes);
in
{
options.modules.services.copyparty = {
enable = lib.mkEnableOption "Copyparty";
package = lib.mkPackageOption pkgs "copyparty-min" { };
port = lib.mkOption {
type = lib.types.port;
default = 3923;
description = "Port Copyparty listens on.";
};
user = lib.mkOption {
type = lib.types.str;
default = "copyparty";
description = "User account that runs Copyparty.";
};
group = lib.mkOption {
type = lib.types.str;
default = "storage";
description = "Group account that owns Copyparty's writable state and served files.";
};
accountName = lib.mkOption {
type = lib.types.str;
default = "alexion";
description = "Copyparty account name configured for password authentication.";
};
passwordFile = lib.mkOption {
type = lib.types.path;
description = "Runtime file containing the Copyparty account password.";
};
stateDir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/copyparty";
description = "Directory where Copyparty stores service state.";
};
volumes = lib.mkOption {
type = lib.types.attrsOf volumeType;
default = { }; default = { };
description = "Copyparty volumes keyed by their URL path."; example = {
dthumb = true;
};
description = "Sets Copyparty volume flags.";
};
};
}
);
default = { };
description = "Defines Copyparty volumes by URL path.";
}; };
reverseProxy = { reverseProxy = {
@@ -151,7 +139,7 @@ in
trustedSources = lib.mkOption { trustedSources = lib.mkOption {
type = lib.types.listOf lib.types.str; type = lib.types.listOf lib.types.str;
default = [ ]; default = [ ];
description = "IP ranges that may supply Copyparty's forwarded client IP header."; description = "Lists proxy sources that can set Copyparty's forwarded client IP header.";
}; };
}; };
}; };
@@ -173,46 +161,49 @@ in
} }
]; ];
users.users.${cfg.user} = { users.users.${serviceUser} = {
isSystemUser = true; isSystemUser = true;
uid = config.registry."stable-uid".${config.networking.hostName}.copyparty; uid = config.registry."stable-uid".${config.networking.hostName}.copyparty;
inherit (cfg) group; group = serviceGroup;
home = cfg.stateDir; home = serviceStateDir;
}; };
systemd.services.copyparty = { systemd.services.copyparty = {
description = "Copyparty file server"; description = "Copyparty file server";
after = [ "network.target" ]; after = [ "network.target" ];
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
preStart = ''
${lib.getExe' pkgs.coreutils "install"} -m 600 ${configFile} /run/copyparty/copyparty.conf
${replacePassword}
'';
serviceConfig = { serviceConfig = {
ReloadSignal = "SIGUSR1"; ReloadSignal = "SIGUSR1";
Type = "simple"; Type = "simple";
User = cfg.user; User = serviceUser;
Group = cfg.group; Group = serviceGroup;
WorkingDirectory = cfg.stateDir; WorkingDirectory = serviceStateDir;
Environment = [ Environment = [
"HOME=${cfg.stateDir}" "HOME=${serviceStateDir}"
"XDG_CONFIG_HOME=${cfg.stateDir}" "XDG_CONFIG_HOME=${serviceStateDir}"
]; ];
StateDirectory = "copyparty"; StateDirectory = "copyparty";
RuntimeDirectory = "copyparty"; RuntimeDirectory = "copyparty";
RuntimeDirectoryMode = "0700"; RuntimeDirectoryMode = "0700";
LoadCredential = [ "password:${cfg.passwordFile}" ]; LoadCredential = [ "${credentialName}:${cfg.passwordFile}" ];
ExecStartPre = configScript; ExecStart = "${lib.getExe pkgs.copyparty-min} -c /run/copyparty/copyparty.conf";
ExecStart = "${lib.getExe cfg.package} -c /run/copyparty/copyparty.conf";
Restart = "on-failure"; Restart = "on-failure";
NoNewPrivileges = true; NoNewPrivileges = true;
PrivateTmp = true; PrivateTmp = true;
ProtectSystem = "strict"; ProtectSystem = "strict";
ProtectHome = true; ProtectHome = true;
ReadWritePaths = [ ReadWritePaths = [
cfg.stateDir serviceStateDir
] ]
++ map (volume: volume.path) (lib.filter (volume: !volume.readOnly) (lib.attrValues cfg.volumes)); ++ map (volume: volume.path) writableVolumes;
}; };
}; };
networking.firewall.allowedTCPPorts = [ cfg.port ]; networking.firewall.allowedTCPPorts = [ port ];
}) })
]; ];
} }
@@ -92,33 +92,33 @@
startScript = pkgs.writeShellScript "palworld-start" '' startScript = pkgs.writeShellScript "palworld-start" ''
set -eu set -eu
${pkgs.coreutils}/bin/install -d \ ${lib.getExe' pkgs.coreutils "install"} -d \
-m 0770 \ -m 0770 \
${lib.escapeShellArg service.stateDir} \ ${lib.escapeShellArg service.stateDir} \
${lib.escapeShellArg (builtins.dirOf savedDir)} ${lib.escapeShellArg (builtins.dirOf savedDir)}
if [ -L ${lib.escapeShellArg savedDir} ]; then if [ -L ${lib.escapeShellArg savedDir} ]; then
current_target="$(${pkgs.coreutils}/bin/readlink ${lib.escapeShellArg savedDir})" current_target="$(${lib.getExe' pkgs.coreutils "readlink"} ${lib.escapeShellArg savedDir})"
if [ "$current_target" != ${lib.escapeShellArg service.stateDir} ]; then if [ "$current_target" != ${lib.escapeShellArg service.stateDir} ]; then
${pkgs.coreutils}/bin/rm ${lib.escapeShellArg savedDir} ${lib.getExe' pkgs.coreutils "rm"} ${lib.escapeShellArg savedDir}
fi fi
fi fi
if [ -d ${lib.escapeShellArg savedDir} ] && [ ! -L ${lib.escapeShellArg savedDir} ]; then if [ -d ${lib.escapeShellArg savedDir} ] && [ ! -L ${lib.escapeShellArg savedDir} ]; then
if ${pkgs.findutils}/bin/find ${lib.escapeShellArg service.stateDir} -mindepth 1 -maxdepth 1 | ${pkgs.gnugrep}/bin/grep -q .; then if ${lib.getExe' pkgs.findutils "find"} ${lib.escapeShellArg service.stateDir} -mindepth 1 -maxdepth 1 | ${lib.getExe' pkgs.gnugrep "grep"} -q .; then
${pkgs.coreutils}/bin/rm -rf ${lib.escapeShellArg savedDir} ${lib.getExe' pkgs.coreutils "rm"} -rf ${lib.escapeShellArg savedDir}
else else
${pkgs.coreutils}/bin/cp -a ${lib.escapeShellArg savedDir}/. ${lib.escapeShellArg service.stateDir}/ ${lib.getExe' pkgs.coreutils "cp"} -a ${lib.escapeShellArg savedDir}/. ${lib.escapeShellArg service.stateDir}/
${pkgs.coreutils}/bin/rm -rf ${lib.escapeShellArg savedDir} ${lib.getExe' pkgs.coreutils "rm"} -rf ${lib.escapeShellArg savedDir}
fi fi
fi fi
if [ ! -e ${lib.escapeShellArg savedDir} ]; then if [ ! -e ${lib.escapeShellArg savedDir} ]; then
${pkgs.coreutils}/bin/ln -s ${lib.escapeShellArg service.stateDir} ${lib.escapeShellArg savedDir} ${lib.getExe' pkgs.coreutils "ln"} -s ${lib.escapeShellArg service.stateDir} ${lib.escapeShellArg savedDir}
fi fi
password="$(${pkgs.coreutils}/bin/tr -d '\n' < ${lib.escapeShellArg service.passwordFile})" password="$(${lib.getExe' pkgs.coreutils "tr"} -d '\n' < ${lib.escapeShellArg service.passwordFile})"
admin_password="$(${pkgs.coreutils}/bin/tr -d '\n' < ${lib.escapeShellArg service.adminPasswordFile})" admin_password="$(${lib.getExe' pkgs.coreutils "tr"} -d '\n' < ${lib.escapeShellArg service.adminPasswordFile})"
exec ./PalServer.sh \ exec ./PalServer.sh \
"$@" \ "$@" \
@@ -145,9 +145,12 @@
] ]
++ lib.optional service.publicLobby "-publiclobby" ++ lib.optional service.publicLobby "-publiclobby"
++ lib.optionals (service.publicIP != null) [ "-publicip=${service.publicIP}" ] ++ lib.optionals (service.publicIP != null) [ "-publicip=${service.publicIP}" ]
++ lib.optional service.rcon.enable "-rcon"; ++ lib.optionals service.rcon.enable [
"-rcon"
"-RCONPort=${toString service.rcon.port}"
];
udpPorts = [ service.port ]; udpPorts = [ service.port ];
tcpPorts = [ service.port ]; tcpPorts = lib.optional service.rcon.enable service.rcon.port;
}; };
} }
); );
@@ -51,7 +51,7 @@
startScript = pkgs.writeShellScript "valheim-start" '' startScript = pkgs.writeShellScript "valheim-start" ''
set -eu set -eu
password="$(${pkgs.coreutils}/bin/tr -d '\n' < ${lib.escapeShellArg service.passwordFile})" password="$(${lib.getExe' pkgs.coreutils "tr"} -d '\n' < ${lib.escapeShellArg service.passwordFile})"
exec ./valheim_server.x86_64 "$@" -password "$password" exec ./valheim_server.x86_64 "$@" -password "$password"
''; '';
in in
+69
View File
@@ -0,0 +1,69 @@
{
config,
lib,
...
}:
let
cfg = config.modules.services.gitea;
in
{
options.modules.services.gitea = {
enable = lib.mkEnableOption "Gitea";
reverseProxyAddress = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "IP address of the reverse proxy trusted to forward client headers.";
};
};
config = lib.mkMerge [
{
registry."stable-uid".${config.networking.hostName}.gitea = 20007;
}
(lib.mkIf cfg.enable {
users.users.gitea = {
isSystemUser = true;
uid = config.registry."stable-uid".${config.networking.hostName}.gitea;
group = "storage";
home = "/var/lib/gitea";
};
networking.firewall.allowedTCPPorts = [
2222
3000
];
services.gitea = {
enable = true;
user = "gitea";
group = "storage";
stateDir = "/var/lib/gitea";
repositoryRoot = "/var/lib/gitea/repositories";
lfs = {
enable = true;
contentDir = "/var/lib/gitea/data/lfs";
};
database.type = "sqlite3";
settings = {
server = {
HTTP_ADDR = "0.0.0.0";
HTTP_PORT = 3000;
ROOT_URL = "https://git.alexion.dev/";
SSH_DOMAIN = "git.alexion.dev";
SSH_PORT = 22;
START_SSH_SERVER = true;
SSH_LISTEN_HOST = "0.0.0.0";
SSH_LISTEN_PORT = 2222;
}
// lib.optionalAttrs (cfg.reverseProxyAddress != null) {
REVERSE_PROXY_TRUSTED_PROXIES = "${cfg.reverseProxyAddress}/32";
};
service.DISABLE_REGISTRATION = true;
session.COOKIE_SECURE = true;
};
};
})
];
}
+3 -2
View File
@@ -5,7 +5,7 @@
... ...
}: }:
let let
cfg = config.modules.services.homepage; # NOLINT(let_order) cfg = config.modules.services.homepage;
derivedAllowedHosts = lib.unique ( derivedAllowedHosts = lib.unique (
lib.optional (selfRoute != null) selfRoute.domain lib.optional (selfRoute != null) selfRoute.domain
@@ -111,7 +111,8 @@ let
let let
sectionOrder = sectionOrderByTab.${tab} or [ ]; sectionOrder = sectionOrderByTab.${tab} or [ ];
in in
sectionOrder ++ lib.filter (section: !lib.elem section sectionOrder) (lib.attrNames sections); lib.filter (section: lib.hasAttr section sections) sectionOrder
++ lib.filter (section: !lib.elem section sectionOrder) (lib.attrNames sections);
in in
{ {
+1 -1
View File
@@ -4,7 +4,7 @@
... ...
}: }:
let let
cfg = config.modules.services.navidrome; # NOLINT(let_order) cfg = config.modules.services.navidrome;
in in
{ {
options.modules.services.navidrome = { options.modules.services.navidrome = {
@@ -40,43 +40,14 @@ let
proxy_pass ${stream.address}:${toString stream.port}; proxy_pass ${stream.address}:${toString stream.port};
} }
'') generatedUdpStreams; '') generatedUdpStreams;
generatedVirtualHosts = generatedVirtualHosts = lib.listToAttrs generatedVirtualHostList;
if duplicateDomainMessages != [ ] then
throw (builtins.head duplicateDomainMessages)
else
lib.listToAttrs generatedVirtualHostList;
duplicateDomainMessages = lib.concatLists ( # Route registry validation already requires unique domains.
lib.mapAttrsToList ( generatedVirtualHostList = lib.concatLists (
domain: virtualHosts:
if lib.length virtualHosts > 1 then
[
"duplicate route domain ${domain} in ${
lib.concatMapStringsSep " and " (
virtualHost: mkRegistryPath virtualHost.registryName virtualHost.host virtualHost.entry
) virtualHosts
}"
]
else
[ ]
) virtualHostsByDomain
);
virtualHostsByDomain = lib.foldl' (
acc: virtualHost:
acc
// {
${virtualHost.name} = (acc.${virtualHost.name} or [ ]) ++ [ virtualHost ];
}
) { } generatedVirtualHostList;
generatedVirtualHostList = generatedHttpsVirtualHostList ++ generatedHttpVirtualHostList;
generatedHttpsVirtualHostList = lib.concatLists (
lib.mapAttrsToList ( lib.mapAttrsToList (
host: routes: host: routes:
lib.mapAttrsToList (entry: _route: mkVirtualHost host entry "https") ( lib.mapAttrsToList (entry: route: mkVirtualHost host entry route.protocol) (
lib.filterAttrs (_entry: route: route.protocol == "https") routes lib.filterAttrs (_entry: route: route.protocol != "udp") routes
) )
) registry.route ) registry.route
); );
@@ -93,8 +64,6 @@ let
inherit (route) port; inherit (route) port;
in in
{ {
inherit host entry;
registryName = "route";
name = route.domain; name = route.domain;
value = { value = {
forceSSL = !isHttp; forceSSL = !isHttp;
@@ -102,21 +71,15 @@ let
extraConfig = lib.optionalString (route.clientMaxBodySize != null) '' extraConfig = lib.optionalString (route.clientMaxBodySize != null) ''
client_max_body_size ${route.clientMaxBodySize}; client_max_body_size ${route.clientMaxBodySize};
''; '';
locations."/".proxyPass = mkBackend address port; locations."/" = {
proxyPass = mkBackend address port;
proxyWebsockets = true;
};
}; };
}; };
mkBackend = address: port: "http://${address}:${toString port}"; mkBackend = address: port: "http://${address}:${toString port}";
generatedHttpVirtualHostList = lib.concatLists (
lib.mapAttrsToList (
host: routes:
lib.mapAttrsToList (entry: _route: mkVirtualHost host entry "http") (
lib.filterAttrs (_entry: route: route.protocol == "http") routes
)
) registry.route
);
mkRegistryPath = mkRegistryPath =
registryName: host: entry: registryName: host: entry:
"registry.${registryName}.${host}.${entry}"; "registry.${registryName}.${host}.${entry}";
+75
View File
@@ -0,0 +1,75 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.modules.services.romm;
in
{
options.modules.services.romm = {
enable = lib.mkEnableOption "RomM";
environmentFile = lib.mkOption {
type = lib.types.path;
default = "/run/secrets/romm.env";
readOnly = true;
description = "Path to RomM's environment file.";
};
};
config = lib.mkMerge [
{
registry."stable-uid".${config.networking.hostName} = {
romm = 20005;
"redis-romm" = 20006;
};
}
(lib.mkIf cfg.enable {
networking.firewall.allowedTCPPorts = [ 80 ];
services.romm = {
enable = true;
package = pkgs.alexion.romm;
group = "storage";
database.createLocally = true;
redis.createLocally = true;
watcher.enable = true;
extraEnvironment = {
HASHEOUS_API_ENABLED = "true";
PLAYMATCH_API_ENABLED = "true";
ROM_CONVERTO_ENABLED = "false";
};
inherit (cfg) environmentFile;
};
systemd.services.romm-worker.serviceConfig.ExecStart =
lib.mkForce "${lib.getExe' config.services.romm.package "romm-worker"} scans";
systemd.tmpfiles.settings."10-romm"."${config.services.romm.dataDir}/config/config.yml"."L+".argument =
toString (
(pkgs.formats.yaml { }).generate "romm-config.yml" {
emulatorjs.auto_save_sync = false;
filesystem.structure = {
default = "roms/{platform}/{game}";
firmware = "bios/{platform}";
};
scan.media = [
"box2d"
"screenshot"
"title_screen"
"logo"
"manual"
];
}
);
users.users = {
romm.uid = config.registry."stable-uid".${config.networking.hostName}.romm;
redis-romm.uid = config.registry."stable-uid".${config.networking.hostName}."redis-romm";
};
})
];
}
+4 -4
View File
@@ -15,9 +15,9 @@
}; };
serviceName = lib.mkOption { serviceName = lib.mkOption {
type = lib.types.str; type = lib.types.strMatching "[a-z0-9][a-z0-9-]*";
example = "valheim"; example = "valheim";
description = "Name of the systemd service that runs the game server."; description = "Lowercase systemd service basename for the game server.";
}; };
appId = lib.mkOption { appId = lib.mkOption {
@@ -87,7 +87,7 @@
prepareScript = pkgs.writeShellScript "steamcmd-${service.serviceName}-prepare" '' prepareScript = pkgs.writeShellScript "steamcmd-${service.serviceName}-prepare" ''
set -eu set -eu
${pkgs.coreutils}/bin/install -d \ ${lib.getExe' pkgs.coreutils "install"} -d \
-o ${user} \ -o ${user} \
-g ${group} \ -g ${group} \
-m 0770 \ -m 0770 \
@@ -155,7 +155,7 @@
wantedBy = lib.mkIf service.autoStart [ "multi-user.target" ]; wantedBy = lib.mkIf service.autoStart [ "multi-user.target" ];
serviceConfig = { serviceConfig = {
Type = "oneshot"; Type = "oneshot";
ExecStart = "${pkgs.systemd}/bin/systemctl --no-block start ${service.serviceName}.service"; ExecStart = "${lib.getExe' pkgs.systemd "systemctl"} --no-block start ${service.serviceName}.service";
}; };
}; };
+1 -4
View File
@@ -5,14 +5,11 @@
... ...
}: }:
# Bazel for the primary user's shell environment. # Bazel for the primary user's shell environment.
let
user = config.user.name;
in
{ {
options.modules.shell.bazel.enable = options.modules.shell.bazel.enable =
lib.mkEnableOption "Bazel for the primary user's shell environment"; lib.mkEnableOption "Bazel for the primary user's shell environment";
config = lib.mkIf config.modules.shell.bazel.enable { config = lib.mkIf config.modules.shell.bazel.enable {
home-manager.users.${user}.home.packages = [ pkgs.bazel ]; home-manager.users.${config.user.name}.home.packages = [ pkgs.bazel ];
}; };
} }
@@ -1,25 +0,0 @@
{
config,
lib,
...
}:
# direnv for the primary user, configured through home-manager.
let
user = config.user.name;
in
{
options.modules.shell.direnv.enable =
lib.mkEnableOption "direnv for the primary user, with nix-direnv shell caching";
config = lib.mkIf config.modules.shell.direnv.enable {
home-manager.users.${user}.programs.direnv = {
enable = true;
silent = true;
# nix-direnv caches the evaluated shell so re-entering a directory is instant
# instead of re-running `nix develop`, and adds the `use flake` stdlib helper.
nix-direnv.enable = true;
stdlib = builtins.readFile ./repo-flake.sh;
};
};
}
@@ -1,33 +0,0 @@
if declare -f use_flake >/dev/null; then
__dotfiles_use_flake_definition="$(declare -f use_flake)"
eval "${__dotfiles_use_flake_definition/use_flake/__dotfiles_nix_direnv_use_flake}"
unset __dotfiles_use_flake_definition
use_flake() {
local flake_expr="${1:-.}"
if [[ "$flake_expr" == //* ]]; then
local git_root
if ! git_root="$(git rev-parse --show-toplevel 2>/dev/null)"; then
log_error 'use flake // requires a Git repository'
return 1
fi
local flake_suffix="${flake_expr#//}"
if [[ -n "$flake_suffix" && "$flake_suffix" != \#* && "$flake_suffix" != /* ]]; then
flake_expr="path:${git_root}/${flake_suffix}"
else
flake_expr="path:${git_root}${flake_suffix}"
fi
shift
__dotfiles_nix_direnv_use_flake "$flake_expr" "$@"
return
fi
__dotfiles_nix_direnv_use_flake "$@"
}
else
log_error 'nix-direnv must define use_flake before the // wrapper loads'
return 1
fi
+1 -1
View File
@@ -6,7 +6,7 @@
}: }:
# fish for the primary user, configured through home-manager. # fish for the primary user, configured through home-manager.
let let
cfg = config.modules.shell.fish; # NOLINT(let_order) cfg = config.modules.shell.fish;
commandsOf = shortcuts: lib.mapAttrs (_name: shortcut: shortcut.command) shortcuts; commandsOf = shortcuts: lib.mapAttrs (_name: shortcut: shortcut.command) shortcuts;
shortcuts = lib.attrByPath [ config.networking.hostName ] { } config.registry.shell-shortcut; shortcuts = lib.attrByPath [ config.networking.hostName ] { } config.registry.shell-shortcut;
user = config.user.name; user = config.user.name;
@@ -47,6 +47,8 @@ or begin
return $status return $status
end end
set remote_nar
if test (count $missing_paths) -gt 0 if test (count $missing_paths) -gt 0
set nar_file (mktemp --suffix=.nar) set nar_file (mktemp --suffix=.nar)
or return $status or return $status
@@ -70,26 +72,23 @@ if test (count $missing_paths) -gt 0
return $scp_status return $scp_status
end end
echo "deploy-to: importing closure on $host" >&2 echo "deploy-to: importing the closure, recording $system_path, and activating it on $host" >&2
ssh -t $host "sudo sh -c 'nix-store --import < $remote_nar' && rm -f $remote_nar"
or begin
echo "deploy-to: closure import failed for $host" >&2
return $status
end
else else
echo "deploy-to: $host already has the full closure for $system_path" >&2 echo "deploy-to: $host already has the full closure for $system_path" >&2
echo "deploy-to: recording $system_path and activating it on $host" >&2
end end
echo "deploy-to: recording $system_path as the system profile on $host" >&2 set remote_script (
ssh -t $host sudo nix-env --profile /nix/var/nix/profiles/system --set $system_path string join '; ' \
or begin 'system_path=$1' \
echo "deploy-to: system profile update failed for $host" >&2 'remote_nar=$2' \
return $status 'if test -n "$remote_nar"; then nix-store --import < "$remote_nar"; rm -f "$remote_nar"; fi' \
end 'nix-env --profile /nix/var/nix/profiles/system --set "$system_path"' \
'"$system_path/bin/switch-to-configuration" switch'
)
echo "deploy-to: activating $system_path on $host" >&2 ssh -t $host sudo sh -e -c (string escape -- $remote_script) sh (string escape -- $system_path $remote_nar)
ssh -t $host sudo "$system_path/bin/switch-to-configuration" switch
or begin or begin
echo "deploy-to: activation failed for $host" >&2 echo "deploy-to: deployment failed for $host" >&2
return $status return $status
end end
@@ -24,6 +24,9 @@ in
home-manager.users.${user} = hm: { home-manager.users.${user} = hm: {
programs.nixvim = { programs.nixvim = {
enable = true; enable = true;
# Aligns Nixvim plugins with this flake's `Nixpkgs`.
# `nixpkgs.useGlobalPackages` prevents Home Manager from creating a separate package set.
nixpkgs.useGlobalPackages = true; nixpkgs.useGlobalPackages = true;
extraPackages = with pkgs; [ extraPackages = with pkgs; [
+3 -7
View File
@@ -12,18 +12,14 @@ let
piDir = "${config.users.users.${user}.home}/.pi/agent"; piDir = "${config.users.users.${user}.home}/.pi/agent";
in in
{ {
options.modules.shell.pi = { options.modules.shell.pi.enable =
enable = lib.mkEnableOption "Pi, a terminal coding agent, configured through home-manager"; lib.mkEnableOption "Pi, a terminal coding agent, configured through home-manager";
};
config = lib.mkIf config.modules.shell.pi.enable { config = lib.mkIf config.modules.shell.pi.enable {
home-manager.users.${user} = { home-manager.users.${user} = {
programs.pi-coding-agent = { programs.pi-coding-agent = {
enable = true; enable = true;
package = pkgs.pi-coding-agent.overrideAttrs { package = pkgs.alexion.pi-coding-agent;
src = ../../../../../third_party/pi;
patches = [ ];
};
settings = { settings = {
defaultProvider = "openai-codex"; defaultProvider = "openai-codex";
+3 -4
View File
@@ -13,9 +13,8 @@ in
lib.mkEnableOption "Python tools for the primary user's shell environment"; lib.mkEnableOption "Python tools for the primary user's shell environment";
config = lib.mkIf config.modules.shell.python.enable { config = lib.mkIf config.modules.shell.python.enable {
home-manager.users.${user}.home = { registry.env.${config.networking.hostName}.PYTHON_TOOLCHAIN_ROOT = "${pkgs.python3}";
sessionVariables.PYTHON_TOOLCHAIN_ROOT = "${pkgs.python3}";
packages = [ pkgs.python3 ]; home-manager.users.${user}.home.packages = [ pkgs.python3 ];
};
}; };
} }
+2 -2
View File
@@ -23,9 +23,9 @@ in
lib.mkEnableOption "Rust tools for the primary user's shell environment"; lib.mkEnableOption "Rust tools for the primary user's shell environment";
config = lib.mkIf config.modules.shell.rust.enable { config = lib.mkIf config.modules.shell.rust.enable {
home-manager.users.${user} = { registry.env.${config.networking.hostName}.RUST_TOOLCHAIN_ROOT = "${toolchain}";
home.sessionVariables.RUST_TOOLCHAIN_ROOT = "${toolchain}";
home-manager.users.${user} = {
home.packages = [ home.packages = [
toolchain toolchain
pkgs.rust-analyzer pkgs.rust-analyzer
+4
View File
@@ -0,0 +1,4 @@
{ lib, ... }:
{
type = lib.types.str;
}
+7
View File
@@ -53,6 +53,13 @@
example = true; example = true;
}; };
locked = lib.mkOption {
description = "Allows the keybind action while the session is locked.";
type = lib.types.bool;
default = false;
example = true;
};
action = lib.mkOption { action = lib.mkOption {
description = "Declares the action this keybind runs."; description = "Declares the action this keybind runs.";
type = lib.types.submodule { type = lib.types.submodule {
+1 -1
View File
@@ -12,7 +12,7 @@ let
in in
{ {
# Next stable UID: 20005 # Next stable UID: 20007
type = lib.types.ints.positive; type = lib.types.ints.positive;
+29
View File
@@ -0,0 +1,29 @@
{ lib, ... }:
{
type = lib.types.submodule {
options = {
position = lib.mkOption {
type = lib.types.enum [
"left"
"center"
"right"
];
default = "right";
description = "Selects the Waybar section that shows the module.";
};
order = lib.mkOption {
type = lib.types.int;
default = 100;
example = 50;
description = "Sorts the module within its Waybar section.";
};
settings = lib.mkOption {
type = lib.types.attrsOf lib.types.anything;
default = { };
description = "Sets the Waybar module configuration.";
};
};
};
}
+19
View File
@@ -0,0 +1,19 @@
{ lib, ... }:
{
type = lib.types.submodule {
options = {
class = lib.mkOption {
description = "Matches the window class reported by the compositor.";
type = lib.types.str;
example = ".*[Ff]irefox.*";
};
icon = lib.mkOption {
description = "Sets the icon shown for matching windows.";
type = lib.types.str;
example = "";
};
};
};
}
+16 -2
View File
@@ -6,6 +6,20 @@ services:
lastfm: lastfm:
api-key: ENC[AES256_GCM,data:Zb0I5TpdEqOxLAD6ed2XywFGZp7dfY69vcGiWOUJkJQ=,iv:pO53pHr09jWfzJyTsQbTHtzTmiQ9+RQkDwZJmInIiX8=,tag:io9jkSN7TF2I8+qlSymaYw==,type:str] api-key: ENC[AES256_GCM,data:Zb0I5TpdEqOxLAD6ed2XywFGZp7dfY69vcGiWOUJkJQ=,iv:pO53pHr09jWfzJyTsQbTHtzTmiQ9+RQkDwZJmInIiX8=,tag:io9jkSN7TF2I8+qlSymaYw==,type:str]
secret: ENC[AES256_GCM,data:rKhd9i0/tbJlXhc9Wf81IDydjpD8khSdwJEEMK260E4=,iv:btBXWBKJp9br5a3yZsRVegN8Ytzc45Qbk2iNlPbENkQ=,tag:LUbu+6gxfqQvVpddZto7Tg==,type:str] secret: ENC[AES256_GCM,data:rKhd9i0/tbJlXhc9Wf81IDydjpD8khSdwJEEMK260E4=,iv:btBXWBKJp9br5a3yZsRVegN8Ytzc45Qbk2iNlPbENkQ=,tag:LUbu+6gxfqQvVpddZto7Tg==,type:str]
romm:
igdb:
client-id: ENC[AES256_GCM,data:tme7NzzbOlCmkMwVObWz793mOsCyVIzSjGoFvxpe,iv:5aOMvsDi8Z9aBymbqhbK79X4kJsqaET1y2Py6YUZZ/U=,tag:ih3GghlxiLsVyeTJoqU9/Q==,type:str]
client-secret: ENC[AES256_GCM,data:AqF7B9VaxM/X3sRqY6C5JVWPWqgRIoqy09P9ZUFj,iv:D+vDPUuGGdzKYnTVTRkI9TV/EOJgVECIeNDt9g8NGl0=,tag:MRaTT7TdEZSd+98xthVw1A==,type:str]
retroachievements:
api-key: ENC[AES256_GCM,data:LMzETQCMi9Ib783W0BZDe2PaSUSTVM5a61502RtZLg8=,iv:Hf5nBoVtZdJszQuc2n0LVNMtJCCpJrh40y4g+l+az70=,tag:esfKLpI1W8BG3Pfsg3xxKQ==,type:str]
steamgriddb:
api-key: ENC[AES256_GCM,data:+kBRieIB/dHbvQLbH2gQTQh2j6DQhybVWEGkSCRZrZY=,iv:3h6dhfiV7HfaZhMv93x8+7F3utzYG6fIbTDScA14PVI=,tag:Wo24YnvsIxe7iMRLyxrj2w==,type:str]
screenscraper:
dev:
id: ENC[AES256_GCM,data:nVPM7ijeVQ==,iv:noknaNqxnTx3E8cKtwY9MVkg7Xeq0C1O+7EpdXvz90g=,tag:f/iHVW1Tu93J3VdvURC7Gg==,type:str]
password: ENC[AES256_GCM,data:6v+we9O7PXExTmFZ,iv:DUEj1pei0ryh4AzTRrB9YDVArLCMvyKPbNfvB2IiyzA=,tag:nPPqB/tbsRqv9W7zFNOsdg==,type:str]
user: ENC[AES256_GCM,data:7hGcFF4xqg==,iv:SFOdYej94Thfn+Te0kXsC9Kq568A1dsnaR+JB90MgBQ=,tag:inIWuFY7f5Tvv8EyV71dYA==,type:str]
password: ENC[AES256_GCM,data:eUWwDDQUSytm/6QZlG5XjbSi41nsBQbm4w==,iv:82S2a3rAVjaF0CXcjXUXErNHMY7MEkjpDL7EVX9cIHw=,tag:uGuVJCv8ThsaNnA0C0WR2Q==,type:str]
sops: sops:
age: age:
- enc: | - enc: |
@@ -26,7 +40,7 @@ sops:
dyjzy0/9Ui1IIXH36AImO5hiEZcrGePV2qPLLQc7ZLngC1jlJuEKJA== dyjzy0/9Ui1IIXH36AImO5hiEZcrGePV2qPLLQc7ZLngC1jlJuEKJA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
recipient: age1wf5s0n0tgt6ld2ysgu9dc67mj8ylwecgl4utzg7hqwy3kut9zyms7aglmh recipient: age1wf5s0n0tgt6ld2ysgu9dc67mj8ylwecgl4utzg7hqwy3kut9zyms7aglmh
lastmodified: "2026-09-12T22:54:25Z" lastmodified: "2026-10-22T16:11:38Z"
mac: ENC[AES256_GCM,data:4R3a0ytf4i8aM8iBQ9vRC/q+hvtjLrCTNgbpCB5DbqBMBYmhtGsBmO/0i1yT0N4tydyLaGOMkNfuuuVi3ASLEOKnViy9w3uD9IN0F79W4f2vguWUVIp/T8skvN9wbV9o9xd0LkJzmeVVgzb1H6HKw+rTGjbquleoIHEBDcDDM+k=,iv:0NlckMXlS+idY6UGBF+F0KFLt+pzD7Q/YEQOdXraAYg=,tag:JBBQduV8uhnKz9gPf6HfAQ==,type:str] mac: ENC[AES256_GCM,data:pkDbhEFKC8fl4SzF3U7F0jqzil9CB803/vIV2mKIDO1MXC8GAOGPW3Q7qfHkCXFkVmXvBvowmJYdR3d/zMO3L4XJPRYR+NpUEpsHjRLq/uSJszWMeCjXQA8DIZxT2fWcp1FGcdpHecrs9QkWTy1OtSDGD+xr0WlHTbLX7bTrtfo=,iv:OfhVrGco4/gBE3V8U7CKDfBGvaCizcEq6x6p/y4X7NY=,tag:/+G5ojgzOlhXW2QM/irWOA==,type:str]
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.13.3 version: 3.13.3
+9 -2
View File
@@ -1,6 +1,13 @@
ssh-host-ed25519-key: ENC[AES256_GCM,data:NMlzM7E9bXUhNqIbtyERuuPShnlx00ftHyRnyMiLSSzp1R/80n8Hdvv1q3uNmZdSgmBYPKdM34fAHuXgwREBcWlqMXptUNnXMngtqN9vxYcfWxJfcN67Fsw2xG8v1h/L0vqwPSn24RAeB6HTExqvr/5egrfQX0yylWytZLMbSIUeAsY+GGD67TDp3W7RdMfXKDHgvRubRR2YdHu8BNQ+BXgzOWCqAbrnHAk0AUaeUloGYr72+zBAhXmWfrXBJjJoU1H7CZELNtcFYczC0wgKUoTTdx9MiPGN2SEx5hCkqOd6iT4MyuY6ZM0SuXMwl7Lw/U12wOzhqZy/1orzQcyRNzcDYcBepAknth/08631fEX4PJdjzZMnI1VTdGSHs/Adl3PQoXv/WGY+QWc6Pb2I+PyAQTCkX9eCr/Mf+VFnOzu0mDBSK/8i1dGlf1lBul4o9L+x/Gz0Fj5kaA1SJdbqCcgKPtEDvLjvCvwYh215BNXv2UCyIrcYf1Y712/sAAcrHmnViocBbTo/m3FkbdGX,iv:jwHCjzmPWv1IXpTonmohIz7LftotOTG0utynf1PKobQ=,tag:1RjXmbJAPvuSUdtCuNXTlg==,type:str] ssh-host-ed25519-key: ENC[AES256_GCM,data:NMlzM7E9bXUhNqIbtyERuuPShnlx00ftHyRnyMiLSSzp1R/80n8Hdvv1q3uNmZdSgmBYPKdM34fAHuXgwREBcWlqMXptUNnXMngtqN9vxYcfWxJfcN67Fsw2xG8v1h/L0vqwPSn24RAeB6HTExqvr/5egrfQX0yylWytZLMbSIUeAsY+GGD67TDp3W7RdMfXKDHgvRubRR2YdHu8BNQ+BXgzOWCqAbrnHAk0AUaeUloGYr72+zBAhXmWfrXBJjJoU1H7CZELNtcFYczC0wgKUoTTdx9MiPGN2SEx5hCkqOd6iT4MyuY6ZM0SuXMwl7Lw/U12wOzhqZy/1orzQcyRNzcDYcBepAknth/08631fEX4PJdjzZMnI1VTdGSHs/Adl3PQoXv/WGY+QWc6Pb2I+PyAQTCkX9eCr/Mf+VFnOzu0mDBSK/8i1dGlf1lBul4o9L+x/Gz0Fj5kaA1SJdbqCcgKPtEDvLjvCvwYh215BNXv2UCyIrcYf1Y712/sAAcrHmnViocBbTo/m3FkbdGX,iv:jwHCjzmPWv1IXpTonmohIz7LftotOTG0utynf1PKobQ=,tag:1RjXmbJAPvuSUdtCuNXTlg==,type:str]
ssh-host-rsa-key: ENC[AES256_GCM,data:Xe0cw0U+ydMzaBbLg+P1JfLQq7uRstJRftpKeMnTSawKmWLYY9sAKRo76YykiYoiQSgb9R+LG/bgM6WnlcqvwVqGhozVnTGE9/ueRWgn4pB9sbT3bRB5F5uQFHJvH3wHjOlUYbllxBVQfE90M/13UQYMKSJEJ9ROdYo3Jpe1lGSTnQi4DKjEjQ2NmL4YEKKgiVkHhsujodnd54l8NMfQTsr0Dd8DpCwxKMriu0dxgJ7Io/v5hsw+tIIB+XXf6nRtkjUJlUylVl4qsZuuqXtAipVtq1g3gIf4J4Gl2q+s4TH531RPhp91dFS5Q4IEJJOOH3pt8ZkUXOZeJ+ilZKr/UV3evNTFq62tzUdMUMauQlggHJrrM+ch7wOmL2E0XCgV5Ld9og6CB79LqqK1lXwRJkFMJsiosTO26/A7YRFkvjFHVRksMHo7Z7LLe+r4CIm1uh/+3f3YSt66BIck1lMmIfmpWIq5KeEhUDKMJU5NQyCk6DTWlyCI5Mvoz2utKV2n3MkoL5X93zR5mdk7M+LXtDe6UE8WUeDABfOd9yWPYJO3IM+0eNZpXN+2jIBPpzWGAjI+Ho3jdANYOOaP3TnIL7iYInLJhbsyfDFlqQKhpcOl6HVvkgXpzABjpYBCpvZAJkqgxXByZyFOJP2sU8mUCoPDuIREZ/OYzTa39c7Nb33FhDECkR/DHo6CI91H642phqe+tv6fOHc6lE8aylDpNB/+ecAKYsKGsUrCZ9fjDt6wuNlL6q0jmktEax30nKnIbK93RuKnsQD1tMqGKubqCLOFux8Eq4XUu0xG/uG2x/UDm1mMguBcEvzLOZ+QmKuC/X2kUlzyhYuADukUqAaWftPjwdnlcBwJ/gZWHDUzw1pXv0VvPyhyFB7xHZfBUVdkTTZmKyQUTNmUUKVCMk8FE4l/LtQY1UizE9Yf3xBPEIbZgldlmUErnVXVOgr8ndoH7/9p7PqwDLNrWZeLplCSiNEDKbtx9F570RU5rgL1lAg3PvsMLsNc+4Oyeb6IE7THvUtFclxbkvDpLm6uNVnHjrUxzd5s+Lb3PXStM3p18Ki+dCbYQStEicod+BVuzYwzIw86tujI9s9aKWinqdffX4/hgB3Yhljg3pThPOxuHCei2RKntDrnqtoRnHF05n2GwIMegtnhlcGmbE+TiTxT6fI+9ewZ/f0/QEd/mLKpdOvxrA/ezxj77Vs0PaeWti/rL0WV7jqa/xxt6F2vN8QgetDomyITtTZxCy5z8n7xJUhXbk31ImlNJVZTXeH1eKGMet6XrYDzsByHzPmt30rFQR8iAfGIDjmGiCwqG24AMH4Mc1UhZ9T8k54F6hWifRRZN99fQf4qb+EhxJe+PfAkOHaoJFsfRulOGpUeTFjIiz7V3ndlFY0oMO7GRKJ1rs5xxINacXU4heZoQmLxeXfZokKgg8jxcqndaz8NBpJyU9b+eHvEj2HXFrinUUOUB9zEl1pFy4ljFTESEVVVs9RawTkM1jKQq4xnYKcHaR7ebqCwrOH/KuurIDNQm6VVue1wUQjDD1qe5sZ2S7d1VrphgSj5O05S+3zdC94UxMWPDjZoo+e31qVO8mIqDqb2qvttdz5ia6vTY4M9FZup2SqiF5r3VI3TW+rntSdwoBOT4AEWjRjUDGneggAu9nKe8N0l3abxvO5iC+vE2TF/2/dIiVTpCaMbpMVEUPGOlWIrgZ0xraDVRl+f39w8JkwlSBTAbWlBsrypGjDzMPhXmrsS2/bbQQDG2GVF+6kJuMWMrbDL14+MlhkyHA2DqE1S9hsP2+WHRSePo/J+SKzaiOonnZJv+XnF+mZSK/CupLjaHkYs0DgiWTZFCdM9cYIONUlUBaGvVHuB+ku21zfNjzHieppxe0Mf9z2D+L9vu1tJO5V9X6msnkWwvgRmugwRpGS00vutMFVrwlsVJhSr3D3CBTGpAmsAQdp9uKbAOrdoD42sBka7N75GYuxxZA7PFsRfEZioaPAjZ80QoBxtYe/G25MmWj3QY516H9pNINo7iZtaCqwxhdwe6dlcm7eFk7l0QJRYklTxhtMWWh5ExvBidRG4A47LJ6XLOIh5PjYRbxMYlbhH0bChCAip2957pZqawcC4s6/7WIHmh1t2MRVznN/x4NV1rVn8nkN3Ch+u/atWe1Q9+t8A16n/Yu7iQtplHnRv3PQxg+x2edefLqDzCpS4q11PrWMWHtbv/VA4NjduVylqCMOBUKGI5VYMq35cxMyuOm0AVHxJcPLNR+hUI3ZkREf9JawzaHxf3EfDfN8opiwbeQasbq53845sbiynuwg6JRuznJhD3U+rZ8hbsDUjFOgGS225G8sUxyYwK45BgXTrjv1I56qL6CIyybsJeP4tT2TTKf9bYwL9/UL41nDi3ceIBXCZYjzz13H3D6wpfMxoUNwIeGS00viUoxnKen9XHefOZEHyVGnMcCu7ehT4BTwaOnlEGWYYLax1AP0Tyr0zqEVQMi55PSRMIOD3LSXR/qPGOyeHSMEbbDUC11zhXrXEv1kFiCzqKDA7qA6mz+J/rsMJ4xXzBEsiQlI833a+LJkX1rR/a7llhTDr49IxpSFa8cns3lIkbTXhVx99DJUW0F2sIlyq9kjVeIY1lnvAiAWi/d+5bxo/xudSob+U993CkJbqDcNE0GU2EB4BbB3s1zGeCqDaQ2E/27uCr/7EId/eQkuo60HsAoTugTZeLI3xFbNkJTn92PyA33ki/nAI0wBm8Inv/yGj6f7IXOJEVYwb2LETUbEJ1gr+VJd+qYx+ejzS2NCTrONl7AdpPv/GSzKyvQ3/JH6CWU7iOZdRFRsi1Y9MB6x54hPbtaEAusAG8IEFSmnHomx5tEL01gsiYsG8B6v30/Yq2UF+tNcjdgLspuhMMpJY9WfeGFg7gazKfSvKxuFgUYYkDQmr2Eqq7jhVvI2vZHQZ8nvn2AGPyxJjuFxeoVAHGQ/UZILiuPaBYYzXSEB7KUDekkh6HaU1mMW0SWxu1K0xYDWYMelIClMRND65Ll4rjfF9xeC9Ft6htD4MFYij70PPPogfh7qIRa1MJb+Lq6YSFj48RMV+S62w1pojoqjmj6n2PhSrOrXyXCqrJHiRBshnzbkpmYH+pQNrg2JojrpZYRKxOJ9Hr0y1DZKPjTcrbuqhiKSNpdMsiK9pkOx56ps5ZCTz86G0HTMxk087xjOgAow4votKXRUFSwZaysfhCKqbiEfKrF37oYyxo86rKVWEA8Dn2MFgdZskFe1nlOszGm78oeu3o9JazfdpXZcg/y3eGuOs0aCEvycVd+EnVJKsztqoLr5eFUY2IlxvUh3ZeXKeQoJaDQek9eM14rQRb6UcbiervIYyWFG8DW2Ryxg7caRClY22sH7iyr0AHrIPVpCBNOsehSsvgPsKih9UqSpsu3ukzITG1q2cEPO6PuE/l0C0hYPsoXK41DA+1hXT1j+D0xYe5AHH3XMMav7p9y7iwZaMvCd+ohVoy+/a2LYKqpLgZq1gOdgD72ES+jnHqLwVMJsAcVnuhku3ENrUNPsxIgimpIS/m9ZeKfGu0pjlxjV87aTAzNDA59kS7XodceRZuou+OTViUVaL/8yKWtDXwLFttakuG6F78hPPp+pe+z41iqUiIAeCbZYwQXnVmc1jGp/qq10PUe5VFf2G53Lz7NCJidtKb0ydbVO3vgf+Lny4lBgXK1sKEdrTw0cOmTpTfqiE7UhRMKUn7UYEsEnX/GP+HQQBEYGA9QJE4INbU7054iSZRdAEpByt15TarSZk7M5jhernXp/vtdD+nekUmWvkxfsgOxLRuT5T2IpxxcS5Ogq5eTVfkSYMPOe1gzEF673BNOr+jKcoU4uKh1BA3MpIoBo++zp/iu6V0GXmmrl9tBv5m2/EAxcoMxS/+RB8hpXsftOPBGI5YxF74unBLeGNkcnELfhAnALpmb27x0x6n39ZpdqQqe6PbEw0K7WCzb4J6ObEuOsJS5yvJZEyxRTJyV0wqy+p2EDHjdl7QDZ6mhE0W4dIMfZO9yzJrNT9ya2rLKtJZsXoVhCCBeUrT1bcpFOotIJr/CmH6G3gAcg9u4e4c5WcHYA/pCwCen+2tsfNHcuYU3S5n21+IamEXZG4Gi0KteSYSV35T660AIlx/N21kT8m6QOSHmQRrd99/JR9C9667k5TMFbTJuSoZQ/bAtw2BmTukquia1WW172niVXNddelwakpjmbHa7b16r3yPv4EIqLz2911RdacjGcTQXmChwrlrMzKtLeLINtnLQytGWUh6uo34wcxgn70qsmArXDaXJXTeJrQ0E9v473mg31jx7Ty3SbQLs55vaRI4I2HicmjX3zOvafILc6NnQZ7C8i0bCpojjXE4Iisa4e5IN4o1J+MBHLaWl3PcqrsorFoacfa47YKPsb29+e6vkxdx77JFRDr2fWJOFrrpt9VGkB8X7n7D1azmWuS9/T8Zb6cGWMhdGY3YFq15qjsxT+NNfx2szbi,iv:i1s5hIhvWr+0Oood4Kftw+zH1sHoyKG7PnCME9zxATM=,tag:/83WXGYbnxRDjJZMB3rQtA==,type:str] ssh-host-rsa-key: ENC[AES256_GCM,data:Xe0cw0U+ydMzaBbLg+P1JfLQq7uRstJRftpKeMnTSawKmWLYY9sAKRo76YykiYoiQSgb9R+LG/bgM6WnlcqvwVqGhozVnTGE9/ueRWgn4pB9sbT3bRB5F5uQFHJvH3wHjOlUYbllxBVQfE90M/13UQYMKSJEJ9ROdYo3Jpe1lGSTnQi4DKjEjQ2NmL4YEKKgiVkHhsujodnd54l8NMfQTsr0Dd8DpCwxKMriu0dxgJ7Io/v5hsw+tIIB+XXf6nRtkjUJlUylVl4qsZuuqXtAipVtq1g3gIf4J4Gl2q+s4TH531RPhp91dFS5Q4IEJJOOH3pt8ZkUXOZeJ+ilZKr/UV3evNTFq62tzUdMUMauQlggHJrrM+ch7wOmL2E0XCgV5Ld9og6CB79LqqK1lXwRJkFMJsiosTO26/A7YRFkvjFHVRksMHo7Z7LLe+r4CIm1uh/+3f3YSt66BIck1lMmIfmpWIq5KeEhUDKMJU5NQyCk6DTWlyCI5Mvoz2utKV2n3MkoL5X93zR5mdk7M+LXtDe6UE8WUeDABfOd9yWPYJO3IM+0eNZpXN+2jIBPpzWGAjI+Ho3jdANYOOaP3TnIL7iYInLJhbsyfDFlqQKhpcOl6HVvkgXpzABjpYBCpvZAJkqgxXByZyFOJP2sU8mUCoPDuIREZ/OYzTa39c7Nb33FhDECkR/DHo6CI91H642phqe+tv6fOHc6lE8aylDpNB/+ecAKYsKGsUrCZ9fjDt6wuNlL6q0jmktEax30nKnIbK93RuKnsQD1tMqGKubqCLOFux8Eq4XUu0xG/uG2x/UDm1mMguBcEvzLOZ+QmKuC/X2kUlzyhYuADukUqAaWftPjwdnlcBwJ/gZWHDUzw1pXv0VvPyhyFB7xHZfBUVdkTTZmKyQUTNmUUKVCMk8FE4l/LtQY1UizE9Yf3xBPEIbZgldlmUErnVXVOgr8ndoH7/9p7PqwDLNrWZeLplCSiNEDKbtx9F570RU5rgL1lAg3PvsMLsNc+4Oyeb6IE7THvUtFclxbkvDpLm6uNVnHjrUxzd5s+Lb3PXStM3p18Ki+dCbYQStEicod+BVuzYwzIw86tujI9s9aKWinqdffX4/hgB3Yhljg3pThPOxuHCei2RKntDrnqtoRnHF05n2GwIMegtnhlcGmbE+TiTxT6fI+9ewZ/f0/QEd/mLKpdOvxrA/ezxj77Vs0PaeWti/rL0WV7jqa/xxt6F2vN8QgetDomyITtTZxCy5z8n7xJUhXbk31ImlNJVZTXeH1eKGMet6XrYDzsByHzPmt30rFQR8iAfGIDjmGiCwqG24AMH4Mc1UhZ9T8k54F6hWifRRZN99fQf4qb+EhxJe+PfAkOHaoJFsfRulOGpUeTFjIiz7V3ndlFY0oMO7GRKJ1rs5xxINacXU4heZoQmLxeXfZokKgg8jxcqndaz8NBpJyU9b+eHvEj2HXFrinUUOUB9zEl1pFy4ljFTESEVVVs9RawTkM1jKQq4xnYKcHaR7ebqCwrOH/KuurIDNQm6VVue1wUQjDD1qe5sZ2S7d1VrphgSj5O05S+3zdC94UxMWPDjZoo+e31qVO8mIqDqb2qvttdz5ia6vTY4M9FZup2SqiF5r3VI3TW+rntSdwoBOT4AEWjRjUDGneggAu9nKe8N0l3abxvO5iC+vE2TF/2/dIiVTpCaMbpMVEUPGOlWIrgZ0xraDVRl+f39w8JkwlSBTAbWlBsrypGjDzMPhXmrsS2/bbQQDG2GVF+6kJuMWMrbDL14+MlhkyHA2DqE1S9hsP2+WHRSePo/J+SKzaiOonnZJv+XnF+mZSK/CupLjaHkYs0DgiWTZFCdM9cYIONUlUBaGvVHuB+ku21zfNjzHieppxe0Mf9z2D+L9vu1tJO5V9X6msnkWwvgRmugwRpGS00vutMFVrwlsVJhSr3D3CBTGpAmsAQdp9uKbAOrdoD42sBka7N75GYuxxZA7PFsRfEZioaPAjZ80QoBxtYe/G25MmWj3QY516H9pNINo7iZtaCqwxhdwe6dlcm7eFk7l0QJRYklTxhtMWWh5ExvBidRG4A47LJ6XLOIh5PjYRbxMYlbhH0bChCAip2957pZqawcC4s6/7WIHmh1t2MRVznN/x4NV1rVn8nkN3Ch+u/atWe1Q9+t8A16n/Yu7iQtplHnRv3PQxg+x2edefLqDzCpS4q11PrWMWHtbv/VA4NjduVylqCMOBUKGI5VYMq35cxMyuOm0AVHxJcPLNR+hUI3ZkREf9JawzaHxf3EfDfN8opiwbeQasbq53845sbiynuwg6JRuznJhD3U+rZ8hbsDUjFOgGS225G8sUxyYwK45BgXTrjv1I56qL6CIyybsJeP4tT2TTKf9bYwL9/UL41nDi3ceIBXCZYjzz13H3D6wpfMxoUNwIeGS00viUoxnKen9XHefOZEHyVGnMcCu7ehT4BTwaOnlEGWYYLax1AP0Tyr0zqEVQMi55PSRMIOD3LSXR/qPGOyeHSMEbbDUC11zhXrXEv1kFiCzqKDA7qA6mz+J/rsMJ4xXzBEsiQlI833a+LJkX1rR/a7llhTDr49IxpSFa8cns3lIkbTXhVx99DJUW0F2sIlyq9kjVeIY1lnvAiAWi/d+5bxo/xudSob+U993CkJbqDcNE0GU2EB4BbB3s1zGeCqDaQ2E/27uCr/7EId/eQkuo60HsAoTugTZeLI3xFbNkJTn92PyA33ki/nAI0wBm8Inv/yGj6f7IXOJEVYwb2LETUbEJ1gr+VJd+qYx+ejzS2NCTrONl7AdpPv/GSzKyvQ3/JH6CWU7iOZdRFRsi1Y9MB6x54hPbtaEAusAG8IEFSmnHomx5tEL01gsiYsG8B6v30/Yq2UF+tNcjdgLspuhMMpJY9WfeGFg7gazKfSvKxuFgUYYkDQmr2Eqq7jhVvI2vZHQZ8nvn2AGPyxJjuFxeoVAHGQ/UZILiuPaBYYzXSEB7KUDekkh6HaU1mMW0SWxu1K0xYDWYMelIClMRND65Ll4rjfF9xeC9Ft6htD4MFYij70PPPogfh7qIRa1MJb+Lq6YSFj48RMV+S62w1pojoqjmj6n2PhSrOrXyXCqrJHiRBshnzbkpmYH+pQNrg2JojrpZYRKxOJ9Hr0y1DZKPjTcrbuqhiKSNpdMsiK9pkOx56ps5ZCTz86G0HTMxk087xjOgAow4votKXRUFSwZaysfhCKqbiEfKrF37oYyxo86rKVWEA8Dn2MFgdZskFe1nlOszGm78oeu3o9JazfdpXZcg/y3eGuOs0aCEvycVd+EnVJKsztqoLr5eFUY2IlxvUh3ZeXKeQoJaDQek9eM14rQRb6UcbiervIYyWFG8DW2Ryxg7caRClY22sH7iyr0AHrIPVpCBNOsehSsvgPsKih9UqSpsu3ukzITG1q2cEPO6PuE/l0C0hYPsoXK41DA+1hXT1j+D0xYe5AHH3XMMav7p9y7iwZaMvCd+ohVoy+/a2LYKqpLgZq1gOdgD72ES+jnHqLwVMJsAcVnuhku3ENrUNPsxIgimpIS/m9ZeKfGu0pjlxjV87aTAzNDA59kS7XodceRZuou+OTViUVaL/8yKWtDXwLFttakuG6F78hPPp+pe+z41iqUiIAeCbZYwQXnVmc1jGp/qq10PUe5VFf2G53Lz7NCJidtKb0ydbVO3vgf+Lny4lBgXK1sKEdrTw0cOmTpTfqiE7UhRMKUn7UYEsEnX/GP+HQQBEYGA9QJE4INbU7054iSZRdAEpByt15TarSZk7M5jhernXp/vtdD+nekUmWvkxfsgOxLRuT5T2IpxxcS5Ogq5eTVfkSYMPOe1gzEF673BNOr+jKcoU4uKh1BA3MpIoBo++zp/iu6V0GXmmrl9tBv5m2/EAxcoMxS/+RB8hpXsftOPBGI5YxF74unBLeGNkcnELfhAnALpmb27x0x6n39ZpdqQqe6PbEw0K7WCzb4J6ObEuOsJS5yvJZEyxRTJyV0wqy+p2EDHjdl7QDZ6mhE0W4dIMfZO9yzJrNT9ya2rLKtJZsXoVhCCBeUrT1bcpFOotIJr/CmH6G3gAcg9u4e4c5WcHYA/pCwCen+2tsfNHcuYU3S5n21+IamEXZG4Gi0KteSYSV35T660AIlx/N21kT8m6QOSHmQRrd99/JR9C9667k5TMFbTJuSoZQ/bAtw2BmTukquia1WW172niVXNddelwakpjmbHa7b16r3yPv4EIqLz2911RdacjGcTQXmChwrlrMzKtLeLINtnLQytGWUh6uo34wcxgn70qsmArXDaXJXTeJrQ0E9v473mg31jx7Ty3SbQLs55vaRI4I2HicmjX3zOvafILc6NnQZ7C8i0bCpojjXE4Iisa4e5IN4o1J+MBHLaWl3PcqrsorFoacfa47YKPsb29+e6vkxdx77JFRDr2fWJOFrrpt9VGkB8X7n7D1azmWuS9/T8Zb6cGWMhdGY3YFq15qjsxT+NNfx2szbi,iv:i1s5hIhvWr+0Oood4Kftw+zH1sHoyKG7PnCME9zxATM=,tag:/83WXGYbnxRDjJZMB3rQtA==,type:str]
ssh-user-ed25519-key: ENC[AES256_GCM,data:xu3YkQnuaVC2YWGPrXfxbgY3PruxfwKMaeBSwyf6HiGOQFn3rlBpcfjtktBayVJkQzdhjK0sMqEBpvljrIOKRDdUC13jCXlvbT9D9P4AtGjzdLO672WZxZ/e+B2jtJGP0qfOo9SSPgsWijbNTy0SXkQoaO5zQe3HUWSH0CSNiNtY88YRodIDcJQVZrwVJndGsHnC5ELVZ60sdzh7rZQeKz+cvigMDpkORcs3QhUe9PFpsdl9emjSlWq+8zJVas6h2mp+ajgGMl8qrb+9mVJMDQIpEmW/HEQIHYLAuIPxyZ43iIeQZC5oPYy518tGZNJUC3KHceTQJgGWHPM707TU1/M7/W47i79TvjWccyQpIv9SQ7G9RJXhzMD15judb5cyQfwobqJ0w4VjTxao3hESZUho8ZMFAyNtXf7IqUgKMmbJ+o4pZTS8Mqyp0ZfjddP7FxnHkPiORmxQ3v2fGqtGTlJ4ODZO/vYZTmwsampWJA2J9FkMihqggI74yyoS8006mkY9kNpeTzNUeF5flFS/,iv:op7zSdx7335l8n/Q3pCM/9enb00Hbs+m3F5NUynNUXw=,tag:F5AE+gB1H1iVXSQWaliWKg==,type:str] ssh-user-ed25519-key: ENC[AES256_GCM,data:xu3YkQnuaVC2YWGPrXfxbgY3PruxfwKMaeBSwyf6HiGOQFn3rlBpcfjtktBayVJkQzdhjK0sMqEBpvljrIOKRDdUC13jCXlvbT9D9P4AtGjzdLO672WZxZ/e+B2jtJGP0qfOo9SSPgsWijbNTy0SXkQoaO5zQe3HUWSH0CSNiNtY88YRodIDcJQVZrwVJndGsHnC5ELVZ60sdzh7rZQeKz+cvigMDpkORcs3QhUe9PFpsdl9emjSlWq+8zJVas6h2mp+ajgGMl8qrb+9mVJMDQIpEmW/HEQIHYLAuIPxyZ43iIeQZC5oPYy518tGZNJUC3KHceTQJgGWHPM707TU1/M7/W47i79TvjWccyQpIv9SQ7G9RJXhzMD15judb5cyQfwobqJ0w4VjTxao3hESZUho8ZMFAyNtXf7IqUgKMmbJ+o4pZTS8Mqyp0ZfjddP7FxnHkPiORmxQ3v2fGqtGTlJ4ODZO/vYZTmwsampWJA2J9FkMihqggI74yyoS8006mkY9kNpeTzNUeF5flFS/,iv:op7zSdx7335l8n/Q3pCM/9enb00Hbs+m3F5NUynNUXw=,tag:F5AE+gB1H1iVXSQWaliWKg==,type:str]
retroarch:
romm:
user: ENC[AES256_GCM,data:Jc1/7lhAhw==,iv:1yFG+9LFbyOHT+xQ3+ZlIiiG4VY7h/FKlgKzgTLV2FA=,tag:6nyway08U8DxFISZQnpmTA==,type:str]
password: ENC[AES256_GCM,data:10KB8nD2HN2FQhWGMoCwxUjzwxA=,iv:xxge3Y7N3T7B7OBIBs7PtmuPXQfrda/bU4LxldGjzuE=,tag:J0Ik7KNZH5mAlHeidZjSYg==,type:str]
retroachievements:
user: ENC[AES256_GCM,data:G6+e2BW8,iv:BJD3nFLWyWX8pFFCKZENOSi6FxCy+BAXOmgdjrCCIak=,tag:yb3VNgBQEN5x7Guqlh8eyg==,type:str]
password: ENC[AES256_GCM,data:kOfDyJK+3WxGDFhu,iv:q/lWpCuuCeyC61QwYQ85oYrXxtiVGyF3UccOVkXt8+w=,tag:k2pwo7R6nmNLiTUp7f70nA==,type:str]
sops: sops:
age: age:
- enc: | - enc: |
@@ -21,7 +28,7 @@ sops:
ZQg0XgccFlZjIBjp5jg2rDq0qG/tFkvIuX9C3udSxyGX+1MRutyhpw== ZQg0XgccFlZjIBjp5jg2rDq0qG/tFkvIuX9C3udSxyGX+1MRutyhpw==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
recipient: age199atsykyh0hp0yuxymznxs0mqv4ram9ttaddk6jrsjjc43rmvu7snh9dq8 recipient: age199atsykyh0hp0yuxymznxs0mqv4ram9ttaddk6jrsjjc43rmvu7snh9dq8
lastmodified: "2026-09-05T00:59:23Z" lastmodified: "2026-10-22T16:53:08Z"
mac: ENC[AES256_GCM,data:zYZoZ3vxcIHTJu2rdEqhsmkCz0ylRo6xXTEQnfBbyeAOP0QD72czo0VfUPHVcZVnLhT3yfwMXjotM2ScwTkUinouOXdW0+jIgHd9U3Q949an0IJGNJVljd3/rN5SknEoTqbA/GRk/uTNUu4A1usWqrp1gSPHFxzALKg/CFJoIag=,iv:SXamTie6plAiFOlZ2rGkpAlRYPzAKfqht0V+stt23jE=,tag:w8xq4orRj9SbDaZ+Y46Epw==,type:str] mac: ENC[AES256_GCM,data:bfXTV8SOfZ88nofmvrzU6CXa/apXHsMvLh0yz3oI9QWyvVmBzW8iv5oUmItQ/GBBM3t3WkFwqqo9sHmImT0GOOg4C8DUUwn/3DP1ehOA6xy/ZDBGNmVZuwqM0boJMRkJBeIYoDX5bChRo7Eg+hMPconLCoqmfZhaIldy6IMOFlY=,iv:4gzsrRKlbcqgkugRdXvtH7KKCUh03oYZyokTtGV8egQ=,tag:+mgqrd+j9pvyFgTwZj5CEw==,type:str]
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.13.3 version: 3.13.3
+2 -1
View File
@@ -5,5 +5,6 @@
"obsidian-style-settings", "obsidian-style-settings",
"custom-font-loader", "custom-font-loader",
"obsidian-icon-folder", "obsidian-icon-folder",
"table-editor-obsidian" "table-editor-obsidian",
"obsidian-linter"
] ]
+15 -1
View File
@@ -28,6 +28,20 @@
"rgb": 5366249 "rgb": 5366249
} }
}, },
{
"query": "path:\"03 wrk/tasks\"[\"status\":open]",
"color": {
"a": 1,
"rgb": 14725458
}
},
{
"query": "path:\"03 wrk/tasks\" [\"status\":closed]",
"color": {
"a": 1,
"rgb": 11657298
}
},
{ {
"query": "path:\"03 wrk\" ", "query": "path:\"03 wrk\" ",
"color": { "color": {
@@ -60,6 +74,6 @@
"repelStrength": 20, "repelStrength": 20,
"linkStrength": 1, "linkStrength": 1,
"linkDistance": 250, "linkDistance": 250,
"scale": 0.3645607001522557, "scale": 0.16202697784544698,
"close": false "close": false
} }
+326
View File
@@ -0,0 +1,326 @@
{
"ruleConfigs": {
"add-blank-line-after-yaml": {
"enabled": true
},
"dedupe-yaml-array-values": {
"enabled": true,
"dedupe-alias-key": true,
"dedupe-tag-key": true,
"dedupe-array-keys": true,
"ignore-keys": []
},
"escape-yaml-special-characters": {
"enabled": true,
"try-to-escape-single-line-arrays": true
},
"force-yaml-escape": {
"enabled": true,
"force-yaml-escape-keys": []
},
"format-tags-in-yaml": {
"enabled": true
},
"format-yaml-array": {
"enabled": true,
"alias-key": true,
"tag-key": true,
"default-array-keys": true,
"force-single-line-array-style": [],
"force-multi-line-array-style": []
},
"insert-yaml-attributes": {
"enabled": true,
"text-to-insert": []
},
"move-inline-fields-to-yaml": {
"enabled": true,
"how-to-handle-full-line-fields": "Move and remove",
"how-to-handle-bracketed-fields": "Leave in place",
"how-to-handle-existing-keys": "Skip",
"inline-keys-to-ignore": []
},
"move-tags-to-yaml": {
"enabled": true,
"how-to-handle-existing-tags": "Nothing",
"tags-to-ignore": []
},
"remove-yaml-keys": {
"enabled": true,
"yaml-keys-to-remove": []
},
"sort-yaml-array-values": {
"enabled": true,
"sort-alias-key": true,
"sort-tag-key": true,
"sort-array-keys": true,
"ignore-keys": [],
"sort-order": "Ascending Alphabetical"
},
"yaml-key-sort": {
"enabled": true,
"yaml-key-priority-sort-order": [
"aliases",
"date-created",
"date-modified"
],
"priority-keys-at-start-of-yaml": true,
"yaml-sort-order-for-other-keys": "None"
},
"yaml-timestamp": {
"enabled": true,
"date-created": true,
"date-created-key": "date-created",
"date-created-source-of-truth": "file system",
"date-modified": true,
"date-modified-key": "date-modified",
"date-modified-source-of-truth": "file system",
"format": "YYYY-MM-DD HH:mm",
"convert-to-utc": false,
"update-on-file-contents-updated": "after 5 seconds"
},
"yaml-title": {
"enabled": false,
"title-key": "title",
"mode": "first-h1-or-filename-if-h1-missing"
},
"yaml-title-alias": {
"enabled": true,
"preserve-existing-alias-section-style": true,
"keep-alias-that-matches-the-filename": false,
"use-yaml-key-to-keep-track-of-old-filename-or-heading": false,
"alias-helper-key": "linter-yaml-title-alias",
"remove-alias-if-empty": true
},
"capitalize-headings": {
"enabled": true,
"style": "Title Case",
"ignore-case-words": [],
"lowercase-words": [],
"starting-word-ignore-characters": "'\"(‘“-",
"ending-word-ignore-characters": ".?!,:;'\")”’0123456789-",
"ignore-words": []
},
"file-name-heading": {
"enabled": true
},
"header-increment": {
"enabled": true,
"start-at-h2": false
},
"headings-start-line": {
"enabled": true
},
"remove-trailing-punctuation-in-heading": {
"enabled": true,
"punctuation-to-remove": ".,;:!。,;:!"
},
"footnote-after-punctuation": {
"enabled": true
},
"move-footnotes-to-the-bottom": {
"enabled": true,
"include-blank-line-between-footnotes": false
},
"re-index-footnotes": {
"enabled": true
},
"auto-correct-common-misspellings": {
"enabled": true,
"ignore-words": [],
"skip-words-with-multiple-capitals": true,
"extra-auto-correct-files": []
},
"blockquote-style": {
"enabled": true,
"style": "space"
},
"convert-bullet-list-markers": {
"enabled": true
},
"default-language-for-code-fences": {
"enabled": true,
"default-language": ""
},
"emphasis-style": {
"enabled": true,
"style": "consistent"
},
"no-bare-urls": {
"enabled": true,
"no-bare-uris": true
},
"ordered-list-style": {
"enabled": true,
"number-style": "ascending",
"list-end-style": ".",
"preserve-start": false
},
"proper-ellipsis": {
"enabled": true
},
"quote-style": {
"enabled": true,
"single-quote-enabled": true,
"single-quote-style": "''",
"double-quote-enabled": true,
"double-quote-style": "\"\""
},
"remove-consecutive-list-markers": {
"enabled": true
},
"remove-empty-list-markers": {
"enabled": true
},
"remove-hyphenated-line-breaks": {
"enabled": true
},
"remove-multiple-spaces": {
"enabled": true
},
"strong-style": {
"enabled": true,
"style": "consistent"
},
"two-spaces-between-lines-with-content": {
"enabled": false,
"line-break-indicator": " "
},
"unordered-list-style": {
"enabled": true,
"list-style": "consistent"
},
"align-table-columns": {
"enabled": true
},
"compact-yaml": {
"enabled": true,
"inner-new-lines": false
},
"consecutive-blank-lines": {
"enabled": true
},
"convert-spaces-to-tabs": {
"enabled": true,
"tabsize": 4
},
"empty-line-around-blockquotes": {
"enabled": true
},
"empty-line-around-code-fences": {
"enabled": true
},
"empty-line-around-horizontal-rules": {
"enabled": true
},
"empty-line-around-math-blocks": {
"enabled": true
},
"empty-line-around-tables": {
"enabled": true
},
"heading-blank-lines": {
"enabled": true,
"bottom": true,
"empty-line-after-yaml": true
},
"line-break-at-document-end": {
"enabled": true
},
"move-math-block-indicators-to-their-own-line": {
"enabled": true
},
"paragraph-blank-lines": {
"enabled": true
},
"remove-empty-lines-between-list-markers-and-checklists": {
"enabled": true
},
"remove-link-spacing": {
"enabled": true
},
"remove-space-around-characters": {
"enabled": true,
"include-fullwidth-forms": true,
"include-cjk-symbols-and-punctuation": true,
"include-dashes": true,
"other-symbols": ""
},
"remove-space-before-or-after-characters": {
"enabled": true,
"characters-to-remove-space-before": ",!?;:).’”]",
"characters-to-remove-space-after": "¿¡‘“(["
},
"space-after-list-markers": {
"enabled": true
},
"space-between-chinese-japanese-or-korean-and-english-or-numbers": {
"enabled": true,
"english-symbols-punctuation-before": "-+;:'\"°%$)]",
"english-symbols-punctuation-after": "-+'\"([¥$"
},
"trailing-spaces": {
"enabled": true,
"two-space-line-break": false
},
"add-blockquote-indentation-on-paste": {
"enabled": true
},
"prevent-double-checklist-indicator-on-paste": {
"enabled": true
},
"prevent-double-list-item-indicator-on-paste": {
"enabled": true
},
"proper-ellipsis-on-paste": {
"enabled": true
},
"remove-hyphens-on-paste": {
"enabled": true
},
"remove-leading-or-trailing-whitespace-on-paste": {
"enabled": true
},
"remove-leftover-footnotes-from-quote-on-paste": {
"enabled": true
},
"remove-multiple-blank-lines-on-paste": {
"enabled": true
}
},
"lintOnSave": true,
"recordLintOnSaveLogs": false,
"displayChanged": true,
"suppressMessageWhenNoChange": true,
"enableDiffPreviewView": true,
"suppressLintAllFilesConfirmationModal": false,
"suppressLintAllFilesInFolderConfirmationModal": false,
"lintOnFileChange": false,
"displayLintOnFileChangeNotice": false,
"settingsConvertedToConfigKeyValues": true,
"textAreaSettingsConvertedToListItemSettings": true,
"defaultArrayStyleMovedToCommonStyles": true,
"additionalFileExtensions": [],
"foldersToIgnore": [
"99 meta/templates"
],
"filesToIgnore": [
{
"label": "todo",
"match": "TODO.md",
"flags": "i"
}
],
"linterLocale": "system-default",
"logLevel": "ERROR",
"lintCommands": [],
"customRegexes": [],
"commonStyles": {
"aliasArrayStyle": "multi-line",
"tagArrayStyle": "single-line",
"defaultArrayStyle": "multi-line",
"minimumNumberOfDollarSignsToBeAMathBlock": 2,
"escapeCharacter": "\"",
"removeUnnecessaryEscapeCharsForMultiLineArrays": true
}
}
File diff suppressed because it is too large. Load diff
+399
View File
@@ -0,0 +1,399 @@
/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin
*/
var Xp=Object.create;var ir=Object.defineProperty;var ef=Object.getOwnPropertyDescriptor;var Hv=Object.getOwnPropertyNames;var $v=Object.getPrototypeOf,Vv=Object.prototype.hasOwnProperty;var tf=(n,t)=>(t=Symbol[n])?t:Symbol.for("Symbol."+n),Dr=n=>{throw TypeError(n)};var nf=(n,t,e)=>t in n?ir(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var Zp=(n,t)=>ir(n,"name",{value:t,configurable:!0});var rr=(n,t)=>()=>{try{return t||n((t={exports:{}}).exports,t),t.exports}catch(e){throw t=0,e}},ud=(n,t)=>{for(var e in t)ir(n,e,{get:t[e],enumerable:!0})},rf=(n,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of Hv(t))!Vv.call(n,r)&&r!==e&&ir(n,r,{get:()=>t[r],enumerable:!(i=ef(t,r))||i.enumerable});return n};var Sn=(n,t,e)=>(e=n!=null?Xp($v(n)):{},rf(t||!n||!n.__esModule?ir(e,"default",{value:n,enumerable:!0}):e,n)),Gv=n=>rf(ir({},"__esModule",{value:!0}),n);var I=n=>[,,,Xp(n?.[tf("metadata")]??null)],sf=["class","method","getter","setter","accessor","field","value","get","set"],ka=n=>n!==void 0&&typeof n!="function"?Dr("Function expected"):n,Qv=(n,t,e,i,r)=>({kind:sf[n],name:t,metadata:i,addInitializer:s=>e._?Dr("Already initialized"):r.push(ka(s||null))}),oe=(n,t)=>nf(t,tf("metadata"),n[3]),L=(n,t,e,i)=>{for(var r=0,s=n[t>>1],a=s&&s.length;r<a;r++)t&1?s[r].call(e):i=s[r].call(e,i);return i},O=(n,t,e,i,r,s)=>{var a,o,l,c,u,d=t&7,m=!!(t&8),p=!!(t&16),h=d>3?n.length+1:d?m?1:2:0,f=sf[d+5],g=d>3&&(n[h-1]=[]),b=n[h]||(n[h]=[]),k=d&&(!p&&!m&&(r=r.prototype),d<5&&(d>3||!p)&&ef(d<4?r:{get[e](){return v(this,s)},set[e](E){return H(this,s,E)}},e));d?p&&d<4&&Zp(s,(d>2?"set ":d>1?"get ":"")+e):Zp(r,e);for(var x=i.length-1;x>=0;x--)c=Qv(d,e,l={},n[3],b),d&&(c.static=m,c.private=p,u=c.access={has:p?E=>Jv(r,E):E=>e in E},d^3&&(u.get=p?E=>(d^1?v:_)(E,r,d^4?s:k.get):E=>E[e]),d>2&&(u.set=p?(E,C)=>H(E,r,C,d^4?s:k.set):(E,C)=>E[e]=C)),o=(0,i[x])(d?d<4?p?s:k[f]:d>4?void 0:{get:k.get,set:k.set}:r,c),l._=1,d^4||o===void 0?ka(o)&&(d>4?g.unshift(o):d?p?s=o:k[f]=o:r=o):typeof o!="object"||o===null?Dr("Object expected"):(ka(a=o.get)&&(k.get=a),ka(a=o.set)&&(k.set=a),ka(a=o.init)&&g.unshift(a));return d||oe(n,r),k&&ir(r,e,k),p?d^4?s:k:r},Ie=(n,t,e)=>nf(n,typeof t!="symbol"?t+"":t,e),md=(n,t,e)=>t.has(n)||Dr("Cannot "+e),Jv=(n,t)=>Object(t)!==t?Dr('Cannot use the "in" operator on this value'):n.has(t),v=(n,t,e)=>(md(n,t,"read from private field"),e?e.call(n):t.get(n)),ee=(n,t,e)=>t.has(n)?Dr("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(n):t.set(n,e),H=(n,t,e,i)=>(md(n,t,"write to private field"),i?i.call(n,e):t.set(n,e),e),_=(n,t,e)=>(md(n,t,"access private method"),e);var No=(n,t,e,i)=>({set _(r){H(n,t,r,e)},get _(){return v(n,t,i)}});var Bo=rr((lf,Fo)=>{(function(n,t){"use strict";typeof define=="function"&&define.amd?define(t):typeof Fo=="object"&&Fo.exports?Fo.exports=t():n.log=t()})(lf,function(){"use strict";var n=function(){},t="undefined",e=typeof window!==t&&typeof window.navigator!==t&&/Trident\/|MSIE /.test(window.navigator.userAgent),i=["trace","debug","info","warn","error"],r={},s=null;function a(h,f){var g=h[f];if(typeof g.bind=="function")return g.bind(h);try{return Function.prototype.bind.call(g,h)}catch{return function(){return Function.prototype.apply.apply(g,[h,arguments])}}}function o(){console.log&&(console.log.apply?console.log.apply(console,arguments):Function.prototype.apply.apply(console.log,[console,arguments])),console.trace&&console.trace()}function l(h){return h==="debug"&&(h="log"),typeof console===t?!1:h==="trace"&&e?o:console[h]!==void 0?a(console,h):console.log!==void 0?a(console,"log"):n}function c(){for(var h=this.getLevel(),f=0;f<i.length;f++){var g=i[f];this[g]=f<h?n:this.methodFactory(g,h,this.name)}if(this.log=this.debug,typeof console===t&&h<this.levels.SILENT)return"No console available for logging"}function u(h){return function(){typeof console!==t&&(c.call(this),this[h].apply(this,arguments))}}function d(h,f,g){return l(h)||u.apply(this,arguments)}function m(h,f){var g=this,b,k,x,E="loglevel";typeof h=="string"?E+=":"+h:typeof h=="symbol"&&(E=void 0);function C(q){var $=(i[q]||"silent").toUpperCase();if(!(typeof window===t||!E)){try{window.localStorage[E]=$;return}catch{}try{window.document.cookie=encodeURIComponent(E)+"="+$+";"}catch{}}}function M(){var q;if(!(typeof window===t||!E)){try{q=window.localStorage[E]}catch{}if(typeof q===t)try{var $=window.document.cookie,j=encodeURIComponent(E),U=$.indexOf(j+"=");U!==-1&&(q=/^([^;]+)/.exec($.slice(U+j.length+1))[1])}catch{}return g.levels[q]===void 0&&(q=void 0),q}}function N(){if(!(typeof window===t||!E)){try{window.localStorage.removeItem(E)}catch{}try{window.document.cookie=encodeURIComponent(E)+"=; expires=Thu, 01 Jan 1970 00:00:00 UTC"}catch{}}}function F(q){var $=q;if(typeof $=="string"&&g.levels[$.toUpperCase()]!==void 0&&($=g.levels[$.toUpperCase()]),typeof $=="number"&&$>=0&&$<=g.levels.SILENT)return $;throw new TypeError("log.setLevel() called with invalid level: "+q)}g.name=h,Line truncated
`,u),d==-1&&(d=l.length-1);var p=l.substring(u,d+1);(i.hasOwnProperty?i.hasOwnProperty(p):i[p]!==void 0)?c+=String.fromCharCode(i[p]):(m==s&&(p=l.substring(u),d=l.length),c+=String.fromCharCode(m),i[p]=m,e[m++]=p),u=d+1}return c}var s=4e4,a=r(n);s=65535;var o=r(t);return{chars1:a,chars2:o,lineArray:e}};D.prototype.diff_charsToLines_=function(n,t){for(var e=0;e<n.length;e++){for(var i=n[e][1],r=[],s=0;s<i.length;s++)r[s]=t[i.charCodeAt(s)];n[e][1]=r.join("")}};D.prototype.diff_commonPrefix=function(n,t){if(!n||!t||n.charAt(0)!=t.charAt(0))return 0;for(var e=0,i=Math.min(n.length,t.length),r=i,s=0;e<r;)n.substring(s,r)==t.substring(s,r)?(e=r,s=e):i=r,r=Math.floor((i-e)/2+e);return r};D.prototype.diff_commonSuffix=function(n,t){if(!n||!t||n.charAt(n.length-1)!=t.charAt(t.length-1))return 0;for(var e=0,i=Math.min(n.length,t.length),r=i,s=0;e<r;)n.substring(n.length-r,n.length-s)==t.substring(t.length-r,t.length-s)?(e=r,s=e):i=r,r=Math.floor((i-e)/2+e);return r};D.prototype.diff_commonOverlap_=function(n,t){var e=n.length,i=t.length;if(e==0||i==0)return 0;e>i?n=n.substring(e-i):e<i&&(t=t.substring(0,e));var r=Math.min(e,i);if(n==t)return r;for(var s=0,a=1;;){var o=n.substring(r-a),l=t.indexOf(o);if(l==-1)return s;a+=l,(l==0||n.substring(r-a)==t.substring(0,a))&&(s=a,a++)}};D.prototype.diff_halfMatch_=function(n,t){if(this.Diff_Timeout<=0)return null;var e=n.length>t.length?n:t,i=n.length>t.length?t:n;if(e.length<4||i.length*2<e.length)return null;var r=this;function s(h,f,g){for(var b=h.substring(g,g+Math.floor(h.length/4)),k=-1,x="",E,C,M,N;(k=f.indexOf(b,k+1))!=-1;){var F=r.diff_commonPrefix(h.substring(g),f.substring(k)),P=r.diff_commonSuffix(h.substring(0,g),f.substring(0,k));x.length<P+F&&(x=f.substring(k-P,k)+f.substring(k,k+F),E=h.substring(0,g-P),C=h.substring(g+F),M=f.substring(0,k-P),N=f.substring(k+F))}return x.length*2>=h.length?[E,C,M,N,x]:null}var a=s(e,i,Math.ceil(e.length/4)),o=s(e,i,Math.ceil(e.length/2)),l;if(!a&&!o)return null;o?a?l=a[4].length>o[4].length?a:o:l=o:l=a;var c,u,d,m;n.length>t.length?(c=l[0],u=l[1],d=l[2],m=l[3]):(d=l[0],m=l[1],c=l[2],u=l[3]);var p=l[4];return[c,u,d,m,p]};D.prototype.diff_cleanupSemantic=function(n){for(var t=!1,e=[],i=0,r=null,s=0,a=0,o=0,l=0,c=0;s<n.length;)n[s][0]==te?(e[i++]=s,a=l,o=c,l=0,c=0,r=n[s][1]):(n[s][0]==ve?l+=n[s][1].length:c+=n[s][1].length,r&&r.length<=Math.max(a,o)&&r.length<=Math.max(l,c)&&(n.splice(e[i-1],0,new D.Diff(ge,r)),n[e[i-1]+1][0]=ve,i--,i--,s=i>0?e[i-1]:-1,a=0,o=0,l=0,c=0,r=null,t=!0)),s++;for(t&&this.diff_cleanupMerge(n),this.diff_cleanupSemanticLossless(n),s=1;s<n.length;){if(n[s-1][0]==ge&&n[s][0]==ve){var u=n[s-1][1],d=n[s][1],m=this.diff_commonOverlap_(u,d),p=this.diff_commonOverlap_(d,u);m>=p?(m>=u.length/2||m>=d.length/2)&&(n.splice(s,0,new D.Diff(te,d.substring(0,m))),n[s-1][1]=u.substring(0,u.length-m),n[s+1][1]=d.substring(m),s++):(p>=u.length/2||p>=d.length/2)&&(n.splice(s,0,new D.Diff(te,u.substring(0,p))),n[s-1][0]=ve,n[s-1][1]=d.substring(0,d.length-p),n[s+1][0]=ge,n[s+1][1]=u.substring(p),s++),s++}s++}};D.prototype.diff_cleanupSemanticLossless=function(n){function t(p,h){if(!p||!h)return 6;var f=p.charAt(p.length-1),g=h.charAt(0),b=f.match(D.nonAlphaNumericRegex_),k=g.match(D.nonAlphaNumericRegex_),x=b&&f.match(D.whitespaceRegex_),E=k&&g.match(D.whitespaceRegex_),C=x&&f.match(D.linebreakRegex_),M=E&&g.match(D.linebreakRegex_),N=C&&p.match(D.blanklineEndRegex_),F=M&&h.match(D.blanklineStartRegex_);return N||F?5:C||M?4:b&&!x&&E?3:x||E?2:b||k?1:0}for(var e=1;e<n.length-1;){if(n[e-1][0]==te&&n[e+1][0]==te){var i=n[e-1][1],r=n[e][1],s=n[e+1][1],a=this.diff_commonSuffix(i,r);if(a){var o=r.substring(r.length-a);i=i.substring(0,i.length-a),r=o+r.substring(0,r.length-a),s=o+s}for(var l=i,c=r,u=s,d=t(i,r)+t(r,s);r.charAt(0)===s.charAt(0);){i+=r.charAt(0),r=r.substring(1)+s.charAt(0),s=s.substring(1);var m=t(i,r)+t(r,s);m>=d&&(d=m,l=i,c=r,u=s)}n[e-1][1]!=l&&(l?n[e-1][1]=l:(n.splice(e-1,1),e--),n[e][1]=c,u?n[e+1][1]=u:(n.splice(e+1,1),e--))}e++}};D.nonAlphaNumericRegex_=/[^a-zA-Z0-9]/;D.whitespaceRegex_=/\s/;D.linebreakRegex_=/[\r\n]/;D.blanklineEndRegex_=/\n\r?\n$/;D.blanklineStartRegex_=/^\r?\n\r?\n/;D.prototype.diff_cleanupEfficiency=function(n){for(var t=!1,e=[],i=0,r=null,s=0,a=!1,o=!1,l=!1,c=!1;s<n.length;)n[s][0]==te?(n[s][1].length<this.Diff_EditCost&&(l||c)?(e[i++]=s,a=l,o=c,r=n[s][1]):(i=0,r=null),l=c=!1):(n[s][0]==ge?c=!0:l=!0,r&&(a&&o&&l&&c||r.length<this.Diff_EditCost/2&&a+o+l+c==3)&&(n.splice(e[i-1],0,new D.Diff(ge,r)),n[e[i-1]+1][0]=ve,i--,r=null,a&&o?(l=c=!0,i=0):(i--,s=i>0?e[i-1]:-1,l=c=!1),t=!0)),s++;t&&this.diff_cleanupMerge(n)};D.prototype.diff_cleanupMerge=function(n){n.push(new D.Diff(te,""));for(var t=0,e=0,i=0,r="",s="",a;t<n.length;)switch(n[t][0]){case ve:i++,s+=n[t][1],t++;break;case ge:e++,r+=n[t][1],t++;break;case te:e+i>1?(e!==0&&i!==0&&(a=this.diff_commonPrefix(s,r),a!==0&&(t-e-i>0&&n[t-e-i-1][0]==te?n[t-e-i-1][1]+=s.substring(0,a):(n.splice(0,0,new D.Diff(te,s.substring(0,a))),t++),s=s.substring(a), Line truncated
`),i=0,r=/^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/;i<e.length;){var s=e[i].match(r);if(!s)throw new Error("Invalid patch string: "+e[i]);var a=new D.patch_obj;for(t.push(a),a.start1=parseInt(s[1],10),s[2]===""?(a.start1--,a.length1=1):s[2]=="0"?a.length1=0:(a.start1--,a.length1=parseInt(s[2],10)),a.start2=parseInt(s[3],10),s[4]===""?(a.start2--,a.length2=1):s[4]=="0"?a.length2=0:(a.start2--,a.length2=parseInt(s[4],10)),i++;i<e.length;){var o=e[i].charAt(0);try{var l=decodeURI(e[i].substring(1))}catch{throw new Error("Illegal escape in patch_fromText: "+l)}if(o=="-")a.diffs.push(new D.Diff(ge,l));else if(o=="+")a.diffs.push(new D.Diff(ve,l));else if(o==" ")a.diffs.push(new D.Diff(te,l));else{if(o=="@")break;if(o!=="")throw new Error('Invalid patch mode "'+o+'" in: '+l)}i++}}return t};D.patch_obj=function(){this.diffs=[],this.start1=null,this.start2=null,this.length1=0,this.length2=0};D.patch_obj.prototype.toString=function(){var n,t;this.length1===0?n=this.start1+",0":this.length1==1?n=this.start1+1:n=this.start1+1+","+this.length1,this.length2===0?t=this.start2+",0":this.length2==1?t=this.start2+1:t=this.start2+1+","+this.length2;for(var e=["@@ -"+n+" +"+t+` @@
`],i,r=0;r<this.diffs.length;r++){switch(this.diffs[r][0]){case ve:i="+";break;case ge:i="-";break;case te:i=" ";break}e[r+1]=i+encodeURI(this.diffs[r][1])+`
`}return e.join("").replace(/%20/g," ")};Qr.exports=D;Qr.exports.diff_match_patch=D;Qr.exports.DIFF_DELETE=ge;Qr.exports.DIFF_INSERT=ve;Qr.exports.DIFF_EQUAL=te});var iv=rr((ZW,nv)=>{nv.exports=YE;var N0=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],F0=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],B0=["Su","Mo","Tu","We","Th","Fr","Sa"],Zc=["January","February","March","April","May","June","July","August","September","October","November","December"],D0=["ACDT","ACST","ACWT","ADT","ACT","AEDT","AEST","AFT","AKDT","AKST","ALMT","AMT","AMST","ANAT","ANAST","AQTT","ART","AST","AWDT","AWST","AZOT","AZOST","AZT","AZST","BNT","BDT","BOT","BRT","BRST","BST","BTT","B","CAST","CAT","CCT","CDT","CEDT","CEST","CET","CHADT","CHAST","CHOT","CHOST","CHsT","CHUT","CIT","CKT","CLST","CLT","COT","CST","CVT","CWST","CXT","C","DAVT","DDUT","DST","EASST","EAST","EAT","ECT","EDT","EEDT","EEST","EET","EGT","EGST","EST","E","EIT","FET","FJT","FJST","FKST","FKT","FNT","F","GALT","GAMT","GET","GFT","GILT","GMT","GST","GYT","G","HADT","HAST","HKT","HOVT","HOVST","HST","ICT","IDT","IOT","IRDT","IRKT","IRKST","IRST","IST","JST","KGT","KOST","KRAT","KRAST","KST","KUYT","LHDT","LHST","LINT","L","MAGT","MAGST","MART","MAWT","MDT","MeST","MHT","MIST","MMT","MSD","MSK","MST","MUT","MVT","MYT","NCT","NDT","NFT","N","NOVT","NOVST","NPT","NRT","NST","NT","NUT","NZDT","NZST","OMST","OMSST","ORAT","O","PDT","PET","PETT","PETST","PGT","PHT","PHOT","PKT","PMDT","PMST","PONT","PST","PWT","PYT","PYST","P","QYZT","RET","ROTT","R","SAKT","SAMT","SAST","SBT","SCT","SGT","SRT","SLT","SLST","SRET","SST","SYOT","TAHT","TFT","TJT","TKT","TLT","TMT","TOT","TRUT","TVT","T","ULAT","ULAST","UTC","UYST","UYT","UZT","U","VET","VLAT","VLAST","VOLT","VUT","V","WAKT","WAT","WAST","WDT","WEDT","WEST","WET","WFT","WGT","WGST","WIB","WIT","WITA","WST","WT","YAKT","YAKST","YAP","YEK","YEKS"],Xc=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],Y0=new RegExp(N0.join("|"),"i"),_0=new RegExp(F0.join("|"),"i"),K0=new RegExp("\\b("+B0.join("|")+")\\b","i"),P0=new RegExp(Zc.join("|"),"i"),z0=new RegExp(Xc.join("|"),"i"),q0=new RegExp("\\b("+D0.join("|")+")\\b","i"),W0=/(\d+)(st|nd|rd|th)\b/i,j0=/(\d{1,4})([/.-])(\d{1,2})[/.-](\d{1,4})/,U0=/((\+|-)(12:00|11:00|10:00|09:30|09:00|08:00|07:00|06:00|05:00|04:00|03:30|03:00|02:00|01:00|00:00|01:00|02:00|03:00|03:30|04:00|04:30|05:00|05:30|05:45|06:00|06:30|07:00|08:00|08:45|09:00|09:30|10:00|10:30|11:00|12:00|12:45|13:00|14:00))$/,H0=/((\+|-)(1200|1100|1000|0930|0900|0800|0700|0600|0500|0400|0330|0300|0200|0100|0000|0100|0200|0300|0330|0400|0430|0500|0530|0545|0600|0630|0700|0800|0845|0900|0930|1000|1030|1100|1200|1245|1300|1400))$/,ma="("+["AM?","PM?"].join("|")+")",$0=new RegExp("0\\d\\:\\d{1,2}\\:\\d{1,2}(\\s*)"+ma,"i"),V0=new RegExp("0\\d\\:\\d{1,2}(\\s*)"+ma,"i"),G0=new RegExp("0\\d(\\s*)"+ma,"i"),Q0=new RegExp("\\d{1,2}\\:\\d{1,2}\\:\\d{1,2}(\\s*)"+ma,"i"),J0=new RegExp("\\d{1,2}\\:\\d{1,2}(\\s*)"+ma,"i"),Z0=new RegExp("\\d{1,2}(\\s*)"+ma,"i"),X0=new RegExp("\\d{1,2}"),eE=new RegExp(Zc.join("|")+"-\\d{2}","i"),tE=new RegExp(Xc.join("|")+"-\\d{2}","i"),Dp=new RegExp("(\\d{1,2})(\\D+)("+Zc.join("|")+"|"+Xc.join("|")+")(\\2)('?\\d{2,4})"),nE=/\d{2}:\d{2}:\d{2}\.\d{3}/,iE=/\d{2}:\d{2}:\d{2}\.\d{2}/,rE=/\d{2}:\d{2}:\d{2}\.\d{1}/,sE=/T\d{2}:\d{2}:\d{2}/,aE=/0\d:\d{2}:\d{2}/,oE=/0\d:\d{2}/,lE=/\b([01]?[0-9]|2[0-3]):[0-5][0-9]:\d{2}/,cE=/\b([01]?[0-9]|2[0-3]):[0-5][0-9]:\d{2}\.\d{3}/,dE=/\b([01]?[0-9]|2[0-3]):[0-5][0-9]:\d{2}\.\d{2}/,uE=/\b([01]?[0-9]|2[0-3]):[0-5][0-9]:\d{2}\.\d{1}/,mE=/\b([01]?[0-9]|2[0-3]):[0-5][0-9]/,pE=/24:00:\d{2}/,fE=/24:00:\d{2}\.\d{3}/,hE=/24:00:\d{2}\.\d{2}/,gE=/24:00:\d{2}\.\d{1}/,yE=/24:00/,bE=/\d{4}/,kE=/\d{2}/,vE=/'\d{2}/,Jk=/0\d/,Zk=/\d{1,2}/,AE=/0\d/,wE=/\d{1,2}/,xE=/^([1-9])\/([1-9]|0[1-9])$/,LE=/^([1-9])\/(1[012])$/,SE=/^(0[1-9]|[12][0-9]|3[01])\/([1-9])$/,EE=/^(0[1-9]|[12][0-9]|3[01])\/(1[012]|0[1-9])$/,TE=/^([1-9])(\D)([1-9][0-9])$/,ME=/^([1-9])(\D)([0][0-9])$/,OE=/^(0[1-9]|1[012])(\D)([1-9][0-9])$/,CE=/^(0[1-9]|1[012])(\D)([0][0-9])$/,Yp=/([/][M]|[M][/]|[MM]|[MMMM])/,Xk=/(D)/,_p=/(Y)/,ev=/\d+\D.+$/,tv=/\D+(\d+)($|Z)/,IE=/M\s*\d{1,2}\b.+$/,RE=/M\D+(0[1-9])\b.+$/,Jc=/\d+\s+(H|h|k)/,NE=/\b(at)\b/i,FE=/\d{13}/,BE=/\d{10}/,DE={"/":"MDY",".":"DMY","-":"YMD"};function YE(n,t){var e=n.toString();if(t=t||{},t.preferredOrder=t.preferredOrder||DE,e=e.replace(FE,"x"),e=e.replace(BE,"X"),e=e.replace(NE,"[$1]"),e.match(Dp)){let[,c,u,d,m,p]=e.match(Dp),h=[];c.length===2&&c[0]==="0"||t.preferLongFormat?h.push("DD"):h.push("D"),h.push(u),d.match(Zc)?h.push("MMMM"):d.match(Xc)?h.push("MMM"):h.push(d),h.push(m),p[0]==="'"?h.push("'YY"):p.length===2?h.push("YY"):(p.length,h.push("YYYY"));var i=h.join("");e=e.replace(Dp,i)}e=e.replace(Y0,"dddd"),e=e.replace(_0,"ddd"),e=e.replace(K0,"dd"),e=e.replace(W0,"Do"),e=e.replace(P0,"MMMM"),e=e.replace(z0,"MMM"),e=e.replace(j0,_E.bind(null,t)),e=e.replace(q0,c=>"["+c+"]"),e=e.replace(U0,"Z"),e=e.replace(H0,"ZZ"),e=e.replace(nE Line truncated
`;e+=`${t.name} ${t.message}`,t.stack&&(e+=`
`+t.stack),ye.default.error(e),va&&Ko(e.substring(e.indexOf("]")+2),ye.default.levels.TRACE)}function qt(n){ye.default.info(`${Do} ${n}`),va&&Ko(n,ye.default.levels.INFO)}function $e(n){ye.default.debug(`${Do} ${n}`),va&&Ko(n,ye.default.levels.DEBUG)}function Wt(n){ye.default.warn(`${Do} ${n}`),va&&Ko(n,ye.default.levels.WARN)}function sr(n){ye.default.getLevel()>ye.default.levels.DEBUG||cf.set(n,performance.now())}function ai(n){if(ye.default.getLevel()>ye.default.levels.DEBUG)return;let t=cf.get(n);if(!t){Wt(A("logs.timing-key-not-found").replace("{TIMING_KEY}",n));return}let e=performance.now()-t;$e(`${n}: ${e} `+A("logs.milliseconds-abbreviation"))}function Ko(n,t){ye.default.getLevel()<=t&&Yo.push(n)}function fd(){Yo=[]}function Yr(n){va=n}function Po(n){if(Xv(n))switch(n){case"INFO":{ye.default.setLevel("info");break}case"TRACE":{ye.default.setLevel("trace");break}case"DEBUG":{ye.default.setLevel("debug");break}case"SILENT":{ye.default.setLevel("silent");break}case"ERROR":{ye.default.setLevel("error");break}case"WARN":{ye.default.setLevel("warn");break}}}function uf(n){switch(n){case ye.default.levels.INFO:return"INFO";case ye.default.levels.TRACE:return"TRACE";case ye.default.levels.DEBUG:return"DEBUG";case ye.default.levels.SILENT:return"SILENT";case ye.default.levels.ERROR:return"ERROR";case ye.default.levels.WARN:return"WARN"}return""}function Xv(n){return Object.values(df).includes(n)}var mf={};var pf={};var ff={};var hf={commands:{"lint-file":{name:"Linten Sie die aktuelle Datei","error-message":"Lint-Datei-Fehler in der Datei"},"lint-file-unless-ignored":{name:"Linten Sie die aktuelle Datei, es sei denn, sie wird ignoriert"},"lint-all-files":{name:"Linten Sie alle Dateien im Vault","error-message":"Beim Linten aller Dateien Fehler in der Datei","success-message":"Alle Dateien gelinted","errors-message-singular":"Beim Linten aller Dateien gab es einen Fehler.","errors-message-plural":"Beim Linten aller Dateien gab es {NUM} Fehler.","start-message":"Dadurch werden alle Ihre Dateien ver\xE4ndert und es k\xF6nnen Fehler entstehen.","submit-button-text":"Linte alle","submit-button-notice-text":"Linte alle Dateien..."},"lint-all-files-in-folder":{name:"Linte alle Dateien im aktuellen Ordner","start-message":"Dadurch werden alle Ihre Dateien in {FOLDER_NAME} bearbeitet, einschlie\xDFlich der Dateien in den Unterordnern, was zu Fehlern f\xFChren kann.","submit-button-text":"Linte alle Dateien in {FOLDER_NAME}","submit-button-notice-text":"Linten aller Dateien in {FOLDER_NAME}...","error-message":"Beim Linten aller Dateien im Ordner gab es Fehler in der Datei","success-message":"Alle {NUM}-Dateien in {FOLDER_NAME} wurden gelinted.","message-singular":"Alle {NUM}-Dateien in {FOLDER_NAME} wurden gelinted und es trat ein Fehler auf.","message-plural":"Alle {FILE_COUNT}-Dateien in {FOLDER_NAME} wurden gelinted und es gab {ERROR_COUNT} Fehler."},"paste-as-plain-text":{name:"Einf\xFCgen als reiner Text und ohne \xC4nderungen"},"lint-file-pop-up-menu-text":{name:"Linte Datei"},"lint-folder-pop-up-menu-text":{name:"Linte Ordner"}},logs:{"plugin-load":"Plugin wird geladen","plugin-unload":"Plugin entladen","folder-lint":"Linting-Ordner ","linter-run":"Laufender Linter","paste-link-warning":"Abgebrochenes Einf\xFCgen des Lints, da der Inhalt der Zwischenablage ein Link ist, wodurch Konflikte mit anderen Plugins vermieden werden, die das Einf\xFCgen \xE4ndern.","see-console":"Weitere Informationen finden Sie in der Konsole.","unknown-error":"Beim Linten ist ein unbekannter Fehler aufgetreten.","moment-locale-not-found":"Beim Versuch, Moment.js locale auf {MOMENT_LOCALE} umzustellen, wurde {CURRENT_LOCALE} angezeigt","file-change-lint-message-start":"Linted","pre-rules":"Regeln vor regul\xE4ren Regeln","post-rules":"Regeln nach regul\xE4ren Regeln","rule-running":"Laufende Regeln","custom-regex":"Benutzerdefinierte Regex-Regeln","running-custom-regex":"Ausf\xFChren von benutzerdefinierten Regex","running-custom-lint-command":"Ausf\xFChren von benutzerdefinierten Lint-Befehlen","custom-lint-duplicate-warning":'Sie k\xF6nnen denselben Befehl ("{COMMAND_NAME}") nicht zweimal als benutzerdefinierte Lint-Regel ausf\xFChren.',"custom-lint-error-message":"Benutzerdefinierter Lint-Befehl","disabled-text":"ist deaktiviert","run-rule-text":"L\xE4uft","timing-key-not-found":"Der Timing-Schl\xFCssel '{TIMING_KEY}' ist in der Timing-Info-Liste nicht vorhanden, daher wurde er ignoriert","milliseconds-abbreviation":"ms","invalid-date-format-error":"Das Format des Erstellungsdatums '{DATE}' konnte nicht analysiert oder bestimmt werden, sodass das Erstellungsdatum in '{FILE_NAME}","invalid-delimiter-error-message":"Trennzeichen darf nur ein einzelnes Zeichen sein","missing-footnote-error-message":"Die Fu\xDFnote '{FOOTNOTE}' hat keinen entsprechenden Fu\xDFnotenverweis vor dem Fu\xDFnoteninhalt und kann nicht verarbeitet werden. Bitte achten Sie darauf, dass alle Fu\xDFnoten vor dem Inhalt der Fu\xDFnote einen entsprechenden Verw Line truncated
`)break;r.trim()===""||r===">"?e=r+e:e="",i--}return[e,i]}function Td(n=""){let[t]=ur(n,n.length);return`
`+t.trim()}function Zf(n="",t=!1,e=1){let i=Td(n),r=Tt(i,">");return(t||Qo.test(n))&&e===r||e<r?i.substring(0,i.lastIndexOf(">")):i}function pA(n,t){if(t===0)return n;let e=t,i=t;for(;e>=0;){let r=n.charAt(e);if(r.trim()!=="")break;r===`
`&&(i=e),e--}return e<0||i===0?n.substring(t+1):n.substring(0,i)+`
`+n.substring(t)}function fA(n,t,e,i=!1,r=!1){if(e===0)return n;let s=t.split(">").length-1,a=e,o=e,l=!1,c="";for(;a>=0;){let b=n.charAt(a);if(b.trim()!==""&&b!==">")break;if(b===">"){if(l)break}else b===`
`&&(o=a,c===`
`&&(l=!0));a--,c=b}if(a<0||o===0)return n.substring(e+1);let u=n.substring(o,e);if(u===`
`||u.startsWith(`
`))return n.substring(0,o)+`
`+n.substring(e);let m=n.lastIndexOf(`
`,o-1),p;m===-1?p=n.substring(0,o):p=n.substring(m,o);let h,f=n.indexOf(`
`,e+1);f===-1?h=n.substring(e):h=n.substring(e,f);let g;return r?g=Zf(p,i,s):Tt(p,">")!=0&&!Qo.test(p)&&(Ca.test(p)||Ca.test(h))?g=n.substring(o,e).trimEnd():g=Td(p),n.substring(0,o)+g+n.substring(e)}function hA(n,t){if(t>=n.length-1)return n;let e=t,i=t,r=!0;for(;e<n.length;){let s=n.charAt(e);if(s.trim()!=="")break;s===`
`&&(r?r=!1:i=e),e++}return e===n.length||i===n.length-1?n.substring(0,t):n.substring(0,t)+`
`+n.substring(i)}function gA(n,t,e,i=!1,r=!1){if(e>=n.length-1)return n;if(n.charAt(e)===">"&&!r){let E=e-1;if(n.charAt(E)===`
`){let C=n.lastIndexOf(`
`,E-1)+1,M=n.substring(C,E);yA(M)&&(e=C-1,e<0&&(e=0))}}let s=t.split(">").length-1,a=e,o=e,l=!0,c=!1,u="",d=!0,m=n.charAt(a-1);for(;a<n.length;){let E=n.charAt(a);if(E.trim()!==""&&E!==">")break;if(E===">"){if(c)break}else E===`
`&&(l?l=!1:o=a,u===`
`&&(c=!0));if(a++,u=E,d&&E===`
`&&r&&m===`
`){o=a;break}d=!1}if(a===n.length||o===n.length-1)return n.substring(0,e);let p=n.substring(e,o);if(p===`
`||p.endsWith(`
`))return n.substring(0,e)+`
`+n.substring(o);let f=n.indexOf(`
`,o+1),g;f===-1?g=n.substring(o):g=n.substring(o+1,f);let b,k=n.lastIndexOf(`
`,e-1);k===-1?b=n.substring(0,o):b=n.substring(k+1,e);let x;if(r){let E=g;g.includes(">")&&(E=t),x=Zf(E,i,s)}else if((Ca.test(g)||Ca.test(b))&&e!=o)x=n.substring(e,o).trimEnd();else{let E=g;g.includes(">")&&(E=t),x=Td(E)}return n.substring(0,e)+x+n.substring(o)}function yA(n){let t=n.trim();if(t==="")return!1;for(let e of t)if(e!==">")return!1;return!0}function mi(n,t,e,i=!1){let[r,s]=ur(n,t);if(r.trim()!==""){let o=Qo.test(n.substring(t,e)),l=Tt(r,">"),c=kA(n,e,l),u=gA(n,r,c,o,i);return s=bA(u,s,l),fA(u,r,s,o,i)}let a=hA(n,e);return pA(a,s)}function Xf(n){return n=n.replaceAll("\\\\","\\"),n=n.replaceAll("\\f","\f"),n=n.replaceAll("\\n",`
`),n=n.replaceAll("\\r","\r"),n=n.replaceAll("\\t"," "),n=n.replaceAll("\\v","\v"),n}function pi(n,t){if(t==0)return t;let e=t;for(;e>0&&n.charAt(e-1)!==`
`;)e--;return e}function Tt(n,t){let e=0;for(let i=0,r=n.length;i<r;i++){let s=n.indexOf(t,i);s>-1&&(e++,i=s)}return e}function Go(n){let t=typeof n;return t!="string"?t==="number":!isNaN(n)&&!isNaN(parseFloat(n))}function bA(n,t,e){let i=t,r=t+1,s,a=!1,o=0;for(;r<n.length;){if(s=n.charAt(r),s.trim()!==""&&s!==">"){a=!0;break}else if(s===`
`){if(o!==e)break;o=0,i=r}else s===">"&&o++;r++}return a?i:t}function kA(n,t,e){let i=t,r=t-1,s,a=!1,o=0;for(;r>=0;){if(s=n.charAt(r),s.trim()!==""&&s!==">"){a=!0;break}else if(s===`
`){if(o!==e)break;o=0,i=r}else s===">"&&o++;r--}return a?i:t}function Hr(n){let t=fi(n),e=new Map,i,r,s;for(let a of t){i=n.substring(a.startIndex,a.endIndex),r=i.split(`
`),r.splice(0,2);for(let o of r){if(s=o.split("|"),s.length!==4){Wt(A("options.custom-auto-correct.custom-row-parse-warning").replace("{ROW}",o));continue}e.set(s[1].trim().toLowerCase(),s[2].trim())}}return e}function eh(n){return n.replace(/[\\[\]<>_*~=`$]/g,"\\$&")}function th(n){return n.replace(/(\\+)([!"#$%&'()*+,-./:;<=>?@[\\\]^_`{|}~])/g,(t,e,i)=>{let r=e.length,s=Math.floor(r/2);return"\\".repeat(s)+i})}function Ge(n,t,e,i){let r=n.length,s=0,a;if(t<0?t=-t>r?0:r+t:t=t>r?r:t,e=e>0?e:0,i.length<1e4)a=Array.from(i),a.unshift(t,e),n.splice(...a);else for(e&&n.splice(t,e);s<i.length;)a=i.slice(s,s+1e4),a.unshift(t,0),n.splice(...a),s+=1e4,t+=1e4}function lt(n,t){return n.length>0?(Ge(n,n.length,0,t),n):t}var vA=hi(/\p{P}/u),De=hi(/[A-Za-z]/),Ye=hi(/[\dA-Za-z]/),nh=hi(/[#-'*+\--9=?A-Z^-~]/);function mr(n){return n!==null&&(n<32||n===127)}var Ra=hi(/\d/),ih=hi(/[\dA-Fa-f]/),Md=hi(/[!-/:-@[-`{-~]/);function K(n){return n!==null&&n<-2}function me(n){return n!==null&&(n<0||n===32)}function Q(n){return n===-2||n===-1||n===32}function pr(n){return Md(n)||vA(n)}var Tn=hi(/\s/);function hi(n){return t;function t(e){return e!==null&&e>-1&&n.test(String.fromCharCode(e))}}function Od(n){if(n===null||me(n)||Tn(n))return 1;if(pr(n))return 2}function $r(n,t,e){let i=[],r=-1;for(;++r<n.length;){let s=n[r].resolveAll;s&&!i.includes(s)&&(t=s(t,e),i.push(s))}return t}var Na={name:"attention",tokenize:wA,resolveAll:AA};function AA(n,t){let e=-1,i,r,s,a,o,l,c,u;for(;++e<n.length;)if(n[e][0]==="enter"&&n[e][1].type==="attentionSequence"&&n[e][1]._close){for(i=e;i--;)if(n[i][0]==="exit"&&n[i][1].type==="attentionSequence"&&n[i][1]._open&&t.sliceSerialize(n[i][1]).charCodeAt(0)===t.sliceSerialize(n[e][1]).charCodeAt(0)){if((n[i][1]._close||n[e][1]._open)&&(n[e][1].end.offset-n[e][1].start.offset)%3&&!((n[i][1].end.offset-n[i][1].start.offset+n[e][1].end.offset-n[e][1].start.offset)%3))continue;l=n[i][1].end.offset-n[i][1].start.offset>1&&n[e][1].end.offset-n[e][1].start.offset>1?2:1;let d=Object.assign({},n[i][1].end),m=Object.assign({},n[e][1].start);rh(d,-l),rh(m,l),a={type:l>1?"strongSequence":"emphasisSequence",start:d,end:Object.assign({},n[i][1].end)},o={type:l>1?"strongSequence":"emphasisSequence",start:Object.assign({},n[e][1].start),end:m},s={type:l>1?"strongText":"emphasisText",start:Object.assign({},n[i][1].end),end:Object.assign({},n[e][1].start)},r={type:l>1?"strong":"emphasis",start:Object.assign({},a.start),end:Object.assign({},o.end)},n[i][1].end=Object.assign({},a.start),n[e][1].start=Object.assign({},o.end),c=[],n[i][1].end.offset-n[i][1].start.offset&&(c=lt(c,[["enter",n[i][1],t],["exit",n[i][1],t]])),c=lt(c,[["enter",r,t],["enter",a,t],["exit",a,t],["enter",s,t]]),c=lt(c,$r(t.parser.constructs.insideSpan.null,n.slice(i+1,e),t)),c=lt(c,[["exit",s,t],["enter",o,t],["exit",o,t],["exit",r,t]]),n[e][1].end.offset-n[e][1].start.offset?(u=2,c=lt(c,[["enter",n[e][1],t],["exit",n[e][1],t]])):u=0,Ge(n,i-1,e-i+3,c),e=i+c.length-u-2;break}}for(e=-1;++e<n.length;)n[e][1].type==="attentionSequence"&&(n[e][1].type="data");return n}function wA(n,t){let e=this.parser.constructs.attentionMarkers.null,i=this.previous,r=Od(i),s;return a;function a(l){return s=l,n.enter("attentionSequence"),o(l)}function o(l){if(l===s)return n.consume(l),o;let c=n.exit("attentionSequence"),u=Od(l),d=!u||u===2&&r||e.includes(l),m=!r||r===2&&u||e.includes(i);return c._open=!!(s===42?d:d&&(r||!m)),c._close=!!(s===42?m:m&&(u||!d)),t(l)}}function rh(n,t){n.column+=t,n.offset+=t,n._bufferIndex+=t}var Cd={name:"autolink",tokenize:xA};function xA(n,t,e){let i=0;return r;function r(p){return n.enter("autolink"),n.enter("autolinkMarker"),n.consume(p),n.exit("autolinkMarker"),n.enter("autolinkProtocol"),s}function s(p){return De(p)?(n.consume(p),a):c(p)}function a(p){return p===43||p===45||p===46||Ye(p)?(i=1,o(p)):c(p)}function o(p){return p===58?(n.consume(p),i=0,l):(p===43||p===45||p===46||Ye(p))&&i++<32?(n.consume(p),o):(i=0,c(p))}function l(p){return p===62?(n.exit("autolinkProtocol"),n.enter("autolinkMarker"),n.consume(p),n.exit("autolinkMarker"),n.exit("autolink"),t):p===null||p===32||p===60||mr(p)?e(p):(n.consume(p),l)}function c(p){return p===64?(n.consume(p),u):nh(p)?(n.consume(p),c):e(p)}function u(p){return Ye(p)?d(p):e(p)}function d(p){return p===46?(n.consume(p),i=0,u):p===62?(n.exit("autolinkProtocol").type="autolinkEmail",n.enter("autolinkMarker"),n.consume(p),n.exit("autolinkMarker"),n.exit("autolink"),t):m(p)}function m(p){if((p===45||Ye(p))&&i++<63){let h=p===45?m:d;return n.consume(p),h}return e(p)}}function G(n,t,e,i){let r=i?i-1:Number.POSITIVE_INFINITY,s=0;return a;function a(l){return Q(l)?(n.enter(e),o(l)):t(l)}function o(l){return Q(l)&&s++<r?(n.consume(l),o):(n.exit(e),t(l))}}var Mn={tokenize:LA,partial:!0};function LA(n,t,e){return i;function i(s){return Q(s)?G(n,r,"linePrefix")(s):r(s)}function r(s){return s===null||K(s)?t(s):e(s)}}var Jo={name:"blockQuote",tokenize:SA,continuation:{tokenize:EA},exit:TA};function SA(n,t,e){letLine truncated
`;break}case-3:{a=`\r
`;break}case-2:{a=t?" ":" ";break}case-1:{if(!t&&r)continue;a=" ";break}default:a=String.fromCharCode(s)}r=s===-2,i.push(a)}return i.join("")}function Qd(n){let i={constructs:ll([Gd,...(n||{}).extensions||[]]),content:r(bh),defined:[],document:r(vh),flow:r(Ah),lazy:{},string:r(xh),text:r(Lh)};return i;function r(s){return a;function a(o){return Th(i,s,o)}}}function Jd(n){for(;!nl(n););return n}var Mh=/[\0\t\n\r]/g;function Zd(){let n=1,t="",e=!0,i;return r;function r(s,a,o){let l=[],c,u,d,m,p;for(s=t+(typeof s=="string"?s.toString():new TextDecoder(a||void 0).decode(s)),d=0,t="",e&&(s.charCodeAt(0)===65279&&d++,e=void 0);d<s.length;){if(Mh.lastIndex=d,c=Mh.exec(s),m=c&&c.index!==void 0?c.index:s.length,p=s.charCodeAt(m),!c){t=s.slice(d);break}if(p===10&&d===m&&i)l.push(-3),i=void 0;else switch(i&&(l.push(-5),i=void 0),d<m&&(l.push(s.slice(d,m)),n+=m-d),p){case 0:{l.push(65533),n++;break}case 9:{for(u=Math.ceil(n/4)*4,l.push(-2);n++<u;)l.push(-1);break}case 10:{l.push(-4),n=1;break}default:i=!0,n=1}d=m+1}return o&&(i&&l.push(-5),t&&l.push(t),l.push(null)),l}}var ox=/\\([!-/:-@[-`{-~])|&(#(?:\d{1,7}|x[\da-f]{1,6})|[\da-z]{1,31});/gi;function Oh(n){return n.replace(ox,lx)}function lx(n,t,e){if(t)return t;if(e.charCodeAt(0)===35){let r=e.charCodeAt(1),s=r===120||r===88;return cl(e.slice(s?2:1),s?16:10)}return Vr(e)||n}function Gr(n){return!n||typeof n!="object"?"":"position"in n||"type"in n?Ch(n.position):"start"in n||"end"in n?Ch(n):"line"in n||"column"in n?Xd(n):""}function Xd(n){return Ih(n&&n.line)+":"+Ih(n&&n.column)}function Ch(n){return Xd(n&&n.start)+"-"+Xd(n&&n.end)}function Ih(n){return n&&typeof n=="number"?n:1}var Nh={}.hasOwnProperty;function eu(n,t,e){return t&&typeof t=="object"&&(e=t,t=void 0),cx(e)(Jd(Qd(e).document().write(Zd()(n,t,!0))))}function cx(n){let t={afterExit:[],beforeEnter:[],transforms:[],canContainEols:["emphasis","fragment","heading","paragraph","strong"],enter:{autolink:a(Gp),autolinkProtocol:q,autolinkEmail:q,atxHeading:a(Hp),blockQuote:a(Fr),characterEscape:q,characterReference:q,codeFenced:a(nr),codeFencedFenceInfo:o,codeFencedFenceMeta:o,codeIndented:a(nr,o),codeText:a(cd,o),codeTextData:q,data:q,codeFlowValue:q,definition:a(_v),definitionDestinationString:o,definitionLabelString:o,definitionTitleString:o,emphasis:a(Kv),hardBreakEscape:a($p),hardBreakTrailing:a($p),htmlFlow:a(Vp,o),htmlFlowData:q,htmlText:a(Vp,o),htmlTextData:q,image:a(Pv),label:o,link:a(Gp),listItem:a(zv),listItemValue:p,listOrdered:a(Qp,m),listUnordered:a(Qp),paragraph:a(qv),reference:kt,referenceString:o,resourceDestinationString:o,resourceTitleString:o,setextHeading:a(Hp),strong:a(Wv),thematicBreak:a(Uv)},exit:{atxHeading:c(),atxHeadingSequence:M,autolink:c(),autolinkEmail:Wn,autolinkProtocol:ha,blockQuote:c(),characterEscapeValue:$,characterReferenceMarkerHexadecimal:Io,characterReferenceMarkerNumeric:Io,characterReferenceValue:Ro,characterReference:We,codeFenced:c(b),codeFencedFence:g,codeFencedFenceInfo:h,codeFencedFenceMeta:f,codeFlowValue:$,codeIndented:c(k),codeText:c(Oe),codeTextData:$,data:$,definition:c(),definitionDestinationString:C,definitionLabelString:x,definitionTitleString:E,emphasis:c(),hardBreakEscape:c(U),hardBreakTrailing:c(U),htmlFlow:c(se),htmlFlowData:$,htmlText:c(ae),htmlTextData:$,image:c(Jt),label:S,labelText:xn,lineEnding:j,link:c(Fe),listItem:c(),listOrdered:c(),listUnordered:c(),paragraph:c(),referenceString:Nr,resourceDestinationString:zt,resourceTitleString:qn,resource:T,setextHeading:c(P),setextHeadingLineSequence:F,setextHeadingText:N,strong:c(),thematicBreak:c()}};Fh(t,(n||{}).mdastExtensions||[]);let e={};return i;function i(R){let Y={type:"root",children:[],position:void 0},Z={stack:[Y],tokenStack:[],config:t,enter:l,exit:u,buffer:o,resume:d,data:e},ie=[],mt=[],we=-1;for(;++we<R.length;)if(mt.push(R[we]),R[we][1].type==="listOrdered"||R[we][1].type==="listUnordered")if(R[we][0]==="enter")ie.push(mt.length-1);else{let pt=ie.pop();s(mt,pt)}for(R=mt,we=-1;++we<R.length;){let pt=t[R[we][0]];R[we][0]==="enter"&&t.beforeEnter.length>0&&r(t.beforeEnter,{...Z,sliceSerialize:R[we][2].sliceSerialize},R[we][1]),Nh.call(pt,R[we][1].type)&&pt[R[we][1].type].call({...Z,sliceSerialize:R[we][2].sliceSerialize},R[we][1]),R[we][0]==="exit"&&t.afterExit.length>0&&r(t.afterExit,{...Z,sliceSerialize:R[we][2].sliceSerialize},R[we][1])}if(Z.tokenStack.length>0){let pt=Z.tokenStack[Z.tokenStack.length-1];(pt[1]||Rh).call(Z,void 0,pt[0])}for(Y.position={start:gi(R.length>0?R[0][1].start:{line:1,column:1,offset:0}),end:gi(R.length>0?R[R.length-2][1].end:{line:1,column:1,offset:0})},we=-1;++we<t.transforms.length;)Y=t.transforms[we](Y)||Y;return Y}function r(R,Y,Z){let ie=-1;for(;++ie<R.length;)R[ie].call(Y,Z)}function s(R,Y){let Z=R.length-1,ie=Y-1,mt=-1,we=!1,pt,Ln,ga,ya,ba=[];for(;++ie<=Z;){let vt=R[ie];switch(vt[1].type){case"listUnordered":case"listOrdered":case"blockQuote":{vt[0]==="enter"?mt++:mt--,ya=void 0;break}case"lineEndingBlank":{vt[0]==="enter"&&(pt&&!ya&&!mt&&!ga&&(ga=ie),ya=voLine truncated
`,Math.max(0,t.startIndex-1));e=e===-1?0:n.lastIndexOf(`
`,Math.max(0,e-1))+1;let i=n.indexOf(`
`,t.endIndex);return i=i===-1?n.length:n.indexOf(`
`,i+1),{startIndex:e,endIndex:i===-1?n.length:i,value:""}}function Ax(n,t){return n.startIndex<=t.endIndex&&t.startIndex<=n.endIndex}function _h(n,t,e){let i=t.map(s=>Bh(e,s)),r=n.map(s=>Bh(e,s));for(let s of i)for(let a of r)if(Ax(s,a))return!1;return n.push(...t),n.sort((s,a)=>s.startIndex-a.startIndex||s.endIndex-a.endIndex),!0}var wx={tokenize:Tx,partial:!0},Kh={tokenize:Mx,partial:!0},Ph={tokenize:Ox,partial:!0},zh={tokenize:Cx,partial:!0},xx={tokenize:Ix,partial:!0},qh={name:"wwwAutolink",tokenize:Sx,previous:jh},Wh={name:"protocolAutolink",tokenize:Ex,previous:Uh},$n={name:"emailAutolink",tokenize:Lx,previous:Hh},On={};function iu(){return{text:On}}var br=48;for(;br<123;)On[br]=$n,br++,br===58?br=65:br===91&&(br=97);On[43]=$n;On[45]=$n;On[46]=$n;On[95]=$n;On[72]=[$n,Wh];On[104]=[$n,Wh];On[87]=[$n,qh];On[119]=[$n,qh];function Lx(n,t,e){let i=this,r,s;return a;function a(d){return!nu(d)||!Hh.call(i,i.previous)||ru(i.events)?e(d):(n.enter("literalAutolink"),n.enter("literalAutolinkEmail"),o(d))}function o(d){return nu(d)?(n.consume(d),o):d===64?(n.consume(d),l):e(d)}function l(d){return d===46?n.check(xx,u,c)(d):d===45||d===95||Ye(d)?(s=!0,n.consume(d),l):u(d)}function c(d){return n.consume(d),r=!0,l}function u(d){return s&&r&&De(i.previous)?(n.exit("literalAutolinkEmail"),n.exit("literalAutolink"),t(d)):e(d)}}function Sx(n,t,e){let i=this;return r;function r(a){return a!==87&&a!==119||!jh.call(i,i.previous)||ru(i.events)?e(a):(n.enter("literalAutolink"),n.enter("literalAutolinkWww"),n.check(wx,n.attempt(Kh,n.attempt(Ph,s),e),e)(a))}function s(a){return n.exit("literalAutolinkWww"),n.exit("literalAutolink"),t(a)}}function Ex(n,t,e){let i=this,r="",s=!1;return a;function a(d){return(d===72||d===104)&&Uh.call(i,i.previous)&&!ru(i.events)?(n.enter("literalAutolink"),n.enter("literalAutolinkHttp"),r+=String.fromCodePoint(d),n.consume(d),o):e(d)}function o(d){if(De(d)&&r.length<5)return r+=String.fromCodePoint(d),n.consume(d),o;if(d===58){let m=r.toLowerCase();if(m==="http"||m==="https")return n.consume(d),l}return e(d)}function l(d){return d===47?(n.consume(d),s?c:(s=!0,l)):e(d)}function c(d){return d===null||mr(d)||me(d)||Tn(d)||pr(d)?e(d):n.attempt(Kh,n.attempt(Ph,u),e)(d)}function u(d){return n.exit("literalAutolinkHttp"),n.exit("literalAutolink"),t(d)}}function Tx(n,t,e){let i=0;return r;function r(a){return(a===87||a===119)&&i<3?(i++,n.consume(a),r):a===46&&i===3?(n.consume(a),s):e(a)}function s(a){return a===null?e(a):t(a)}}function Mx(n,t,e){let i,r,s;return a;function a(c){return c===46||c===95?n.check(zh,l,o)(c):c===null||me(c)||Tn(c)||c!==45&&pr(c)?l(c):(s=!0,n.consume(c),a)}function o(c){return c===95?i=!0:(r=i,i=void 0),n.consume(c),a}function l(c){return r||i||!s?e(c):t(c)}}function Ox(n,t){let e=0,i=0;return r;function r(a){return a===40?(e++,n.consume(a),r):a===41&&i<e?s(a):a===33||a===34||a===38||a===39||a===41||a===42||a===44||a===46||a===58||a===59||a===60||a===63||a===93||a===95||a===126?n.check(zh,t,s)(a):a===null||me(a)||Tn(a)?t(a):(n.consume(a),r)}function s(a){return a===41&&i++,n.consume(a),r}}function Cx(n,t,e){return i;function i(o){return o===33||o===34||o===39||o===41||o===42||o===44||o===46||o===58||o===59||o===63||o===95||o===126?(n.consume(o),i):o===38?(n.consume(o),s):o===93?(n.consume(o),r):o===60||o===null||me(o)||Tn(o)?t(o):e(o)}function r(o){return o===null||o===40||o===91||me(o)||Tn(o)?t(o):i(o)}function s(o){return De(o)?a(o):e(o)}function a(o){return o===59?(n.consume(o),i):De(o)?(n.consume(o),a):e(o)}}function Ix(n,t,e){return i;function i(s){return n.consume(s),r}function r(s){return Ye(s)?e(s):t(s)}}function jh(n){return n===null||n===40||n===42||n===95||n===91||n===93||n===126||me(n)}function Uh(n){return!De(n)}function Hh(n){return!(n===47||nu(n))}function nu(n){return n===43||n===45||n===46||n===95||Ye(n)}function ru(n){let t=n.length,e=!1;for(;t--;){let i=n[t][1];if((i.type==="labelLink"||i.type==="labelImage")&&!i._balanced){e=!0;break}if(i._gfmAutolinkLiteralWalkedInto){e=!1;break}}return n.length>0&&!e&&(n[n.length-1][1]._gfmAutolinkLiteralWalkedInto=!0),e}function su(n,t){let e=String(n);if(typeof t!="string")throw new TypeError("Expected character");let i=0,r=e.indexOf(t);for(;r!==-1;)i++,r=e.indexOf(t,r+t.length);return i}function au(n){if(typeof n!="string")throw new TypeError("Expected a string");return n.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d")}function ou(n,t,e){let r=_r((e||{}).ignore||[]),s=Rx(t),a=-1;for(;++a<s.length;)wa(n,"text",o);function o(c,u){let d=-1,m;for(;++d<u.length;){let p=u[d],h=m?m.children:void 0;if(r(p,h?h.indexOf(p):void 0,m))return;m=p}if(m)return l(c,u)}function l(c,u){let d=u[u.length-1],m=s[a][0],p=s[a][1],h=0,g=d.children.indexOf(c),b=!1,k=[];m.lastIndex=0;let x=m.exec(c.value);for(;x;){let E=x.index,C={index:x.index,input:x.input,stack:[...u,c]},M=p(...x,C);if(typeof M=="string"&&(M=M.length>0?{type:"text",value:M}:void 0),M===!1?m.lastIndex=E+1:(h!==E&&k.push({type:"text",value:c.value.slice(h,E)}),Array. Line truncated
`?(e++,i=1):i++;return{line:e,column:i,offset:t}}function yi(n,t=!1){let e=Jh(n),i=[];return ar(e,"listItem",r=>{if(!r.children||r.children.length===0){t&&i.push({position:r.position,isEmpty:!0});return}for(let s of r.children)s.type==="paragraph"&&i.push({position:s.position,isEmpty:!1})}),i.sort((r,s)=>s.position.start.offset-r.position.start.offset),i}function Xh(n){let t=Jh(n),e=[];return ar(t,"heading",i=>{if(!(!i.children||i.children.length===0))for(let r of i.children)r.type==="text"&&e.push({position:r.position,text:r.value})}),e.sort((i,r)=>r.position.start.offset-i.position.start.offset),e}function eg(n,t,e){let i=ot("footnoteDefinition",n).filter(c=>!e.isProtected(c.start.offset,n.indexOf("]",c.start.offset)+2)),r=[],s=new Map,a=new Map,o=function(c,u,d){let m=u.match(/\[\^.*?\]/)[0];if(s.has(m)){let g=s.get(m);g.footnotesReferencingKey.push(u),s.set(m,g);return}let p,h=[];do{if(d<0)break;p=c.lastIndexOf(m,d),p!==-1&&(e.isProtected(p,p+m.length)||h.push(p),d=p-1)}while(p>0);let f={key:m,referencePositions:h,footnotesReferencingKey:[u]};s.set(m,f)};for(let c of i){let u=n.substring(c.start.offset,c.end.offset);r.push(u),o(n,u,c.start.offset-1)}for(let c of i)c.end.offset<n.length&&n[c.end.offset]===`
`&&(n=n.substring(0,c.end.offset)+n.substring(c.end.offset+1)),c.end.offset<n.length&&n[c.end.offset]===`
`&&(n=n.substring(0,c.end.offset)+n.substring(c.end.offset+1)),n=n.substring(0,c.start.offset)+n.substring(c.end.offset);for(let c of s){let u=c[1],d=u.referencePositions.length-u.footnotesReferencingKey.length;d=d>=0?d:0;let m=0;for(let p of u.footnotesReferencingKey){if(m+d>=u.referencePositions.length)throw new Error(A("logs.missing-footnote-error-message").replace("{FOOTNOTE}",p));a.set(p,u.referencePositions[d+m++])}}r=r.sort((c,u)=>a.get(c)-a.get(u)),r.length>0&&(n=n.trimEnd());let l=`
`;t?l=`
`:r.length>0&&(n+=`
`);for(let c of r)n+=l+c;return n}function tg(n,t){let e=ot("footnoteDefinition",n).filter(f=>!t.isProtected(f.start.offset,n.indexOf("]",f.start.offset)+2)),i=[],r=new Map,s=new Map,a=[],o=new Set,l=function(f,g,b){let k=g.match(/\[\^.*?\]/)[0];r.set(g,k);let x=o.has(k);if(x&&i.includes(g))return;if(x)throw new Error(A("logs.too-many-footnotes-error-message").replace("{FOOTNOTE_KEY}",k));let E;do E=f.lastIndexOf(k,b),E!==-1&&(!t.isProtected(E,E+k.length)&&(E+g.length>f.length||f.substring(E,E+g.length)!==g)&&a.push({key:k,position:E}),b=E-1);while(E>0);o.add(k)};for(let f of e){let g=n.substring(f.start.offset,f.end.offset);i.unshift(g),l(n,g,f.start.offset)}let c=1,u=new Set;for(let f of i){if(u.has(f))continue;u.add(f);let g=r.get(f),b=`[^${c++}]`;s.set(g,b)}a.sort((f,g)=>g.position-f.position);let d=[],m=[];for(let f of a){let g=s.get(f.key);d.push({startIndex:f.position,endIndex:f.position+f.key.length,value:g})}u.clear();for(let f of e.slice().reverse()){let g=n.substring(f.start.offset,f.end.offset);if(u.has(g)){let x=f.start.offset;n[x-1]===`
`&&n[f.end.offset]===`
`&&x--,m.push({startIndex:x,endIndex:f.end.offset,value:""});continue}u.add(g);let b=r.get(g),k=s.get(b);d.some(x=>x.startIndex===f.start.offset)||d.push({startIndex:f.start.offset,endIndex:f.start.offset+b.length,value:k})}let p=new Et(m),h=d.filter(f=>!p.isProtected(f.startIndex,f.endIndex));return h.push(...p.ranges.map(f=>({...f,value:""}))),ke(n,h.sort((f,g)=>f.startIndex-g.startIndex))}function dl(n,t,e,i){let r=e==="strong"?2:1,s=ot(e,n).filter(l=>!i.isProtected(l.start.offset,l.start.offset+r)&&!i.isProtected(l.end.offset-r,l.end.offset));if(s.length===0)return n;let a;if(t==="underscore")a="_";else if(t==="asterisk")a="*";else{let l=s[s.length-1];a=n.substring(l.start.offset,l.start.offset+1)}e==="strong"&&(a+=a);let o=[];for(let l of s)o.push({startIndex:l.start.offset,endIndex:l.start.offset+a.length,value:a}),o.push({startIndex:l.end.offset-a.length,endIndex:l.end.offset,value:a});return J(n,o)}function ng(n,t,e){let i=e.projection(),r=kr("paragraph",i);if(r.length===0)return n;n=i.text;for(let s of r){let a=n.substring(s.startIndex,s.endIndex).split(`
`),o=a.length-1;if(o<1)continue;let l=0;if(!(Lg.test(a[0])&&a[1].startsWith(">")&&(l=1,o<2))){for(let c=l;c<o;c++){let u=a[c];Vx(u,t)||(a[c]=Gx(u,t))}n=ui(n,s.startIndex,s.endIndex,a.join(`
`))}}return vr(i,n)}function Vx(n,t){return!!(n.endsWith("<br>")&&t=="<br>"||n.endsWith("<br/>")&&t=="<br/>"||n.endsWith(" ")&&t==" "||!n.endsWith("\\\\")&&n.endsWith("\\")&&t=="\\")}function Gx(n,t){n=n.trimEnd();let e=0;return n.endsWith("<br>")&&(e=4),n.endsWith("<br/>")&&(e=5),!n.endsWith("\\\\")&&n.endsWith("\\")&&(e=1),e&&(n=n.substring(0,n.length-e)),n.trimEnd()+t}function ig(n,t){let e=t.projection();n=e.text;let i=n.endsWith(`
`),r=ot("paragraph",n);if(r.length===0)return e.source;let s=[],a=new Map,o=(l,c,u)=>{let d=`${l}:${c}`,m=a.get(d);if(m){if(m.value!=u)throw new Error(A("logs.paragraph-gap-conflict-error"));return}let p={startIndex:l,endIndex:c,value:u};a.set(d,p),s.push(p)};for(let l of r){let c=l.start.offset;for(c>0&&c--;c>=0&&n.charAt(c)!=`
`;)c--;c++;let u=n.substring(c,l.end.offset).split(`
`),d=u[0].trimStart();if(d.startsWith(">")||d.match(ul)||d.match(ml))continue;let m=c;for(let b=0;b<u.length-1;b++){let k=u[b];m+=k.length;let x=k.endsWith("<br>")||k.endsWith("<br/>")||k.endsWith(" ")||!k.endsWith("\\\\")&&k.endsWith("\\");s.push({startIndex:m,endIndex:m+1,value:x?`
`:`
`}),m++}let p=c;for(;c>0&&n.charAt(c-1)==`
`;)c--;o(c,p,c==0?"":`
`);let h=n.length,f=l.end.offset;for(f<h&&f++;f<h&&n.charAt(f)==`
`;)f++;let g=`
`;f==h&&(g=i?`
`:""),o(l.end.offset,f,g)}return vr(e,J(n,s))}function rg(n,t){let e=ot("link",n),i=[];for(let r of e){if(r==null||t.isProtected(r.start.offset,r.end.offset))continue;let s=n.substring(r.start.offset,r.end.offset);if(!s.match(Ar))continue;let a=s.indexOf("]"),o=s.substring(0,1)+s.substring(1,a).trim()+s.substring(a);i.push({startIndex:r.start.offset,endIndex:r.end.offset,value:o})}return J(n,i)}function sg(n,t,e){let i=ot("emphasis",n),r=[];for(let s of i)e.isProtected(s.start.offset,s.start.offset+1)||e.isProtected(s.end.offset-1,s.end.offset)||r.push(...t(n.substring(s.start.offset+1,s.end.offset-1),s.start.offset+1,e));return r}function ag(n,t,e){let i=ot("strong",n),r=[];for(let s of i)e.isProtected(s.start.offset,s.start.offset+2)||e.isProtected(s.end.offset-2,s.end.offset)||r.push(...t(n.substring(s.start.offset+2,s.end.offset-2),s.start.offset+2,e));return r}function kr(n,t){let e=[];for(let i of ot(n,t.source)){let r=t.sourceToProjection(i.start.offset),s=t.sourceToProjection(i.end.offset);r!==void 0&&s!==void 0&&!t.isToken(r)&&e.push({startIndex:r,endIndex:s})}return e}function vr(n,t){let e=[];for(let i of Ue(n.text,t)){let r=n.editRangeToSource(i);r&&e.push({...r,value:i.value})}return J(n.source,e)}function og(n,t){let e=Ue(n.text,t),i=s=>{let a=0;for(let o of e){if(o.startIndex>s)break;if(o.endIndex>s)return;a+=o.value.length-(o.endIndex-o.startIndex)}return s+a},r=[];for(let s of kr("inlineMath",n)){let a=i(s.startIndex),o=i(s.endIndex);a!==void 0&&o!==void 0&&r.push({startIndex:a,endIndex:o})}return r}function lg(n,t){let e=t.projection(),i=e.text,r=kr("code",e);for(let s of r){let a=i.substring(s.startIndex,s.endIndex);!a.startsWith("```")&&!a.startsWith("~~~")||(i=mi(i,s.startIndex,s.endIndex))}return vr(e,i)}function cg(n,t,e){let i=e.projection(),r=i.text,s=kr("math",i);for(let a of s)r=mi(r,a.startIndex,a.endIndex);s=og(i,r);for(let a of s)r.substring(a.startIndex,a.endIndex).startsWith("$".repeat(t))&&(r=mi(r,a.startIndex,a.endIndex));return vr(i,r)}function dg(n,t){let e=t.projection(),i=e.text,r=kr("blockquote",e);for(let s of r){let a=s.endIndex;for(;a<i.length-1&&i.charAt(a)!==`
`;)a++;i=mi(i,s.startIndex,a,!0)}return vr(e,i)}function ug(n,t){let e=t.projection(),i=e.text,r=kr("thematicBreak",e);for(let s of r)i=mi(i,s.startIndex,s.endIndex);return vr(e,i)}function mg(n,t,e,i,r){let s=ot("list",n);if(!s)return n;let a=/^(( |\t|> )*)((\d+(\.|\)))|[-*+])([^\n]*)$/gm,o=new Set,l=0,c=0;for(let u of n.matchAll(a)){l+=Tt(n.substring(c,u.index),`
`),c=u.index;let d=u.index+u[1].length;r.isProtected(d,d+u[3].length)&&o.add(l)}for(let u of s){let d=u.start.offset;for(;d>0&&n.charAt(d-1)!==`
`;)d--;let m=n.substring(d,u.end.offset),p=function(x){let E=x.lastIndexOf("> ");return E!==-1&&(x=x.substring(E+2)),x=x.replaceAll(" "," "),Math.floor((x.split(" ").length-1)/2)+1},h=new Map,f=function(x,E){let C=E;for(;C>x;)h.delete(C--)},g=-1,b=Tt(n.substring(0,d),`
`),k=0;m=m.replace(a,(x,E="",C,M,N,F,P,q)=>{if(b+=Tt(m.substring(k,q),`
`),k=q,o.has(b))return x;let $=t==="preserve"||i?parseInt(N,10):1,j=p(E);if(!/^\d/.test(M)){let U=j>g?j:g;return f(j,U),x}return h.has(j)?t==="ascending"?($=h.get(j)+1,h.set(j,$)):i&&($=h.get(j)):h.set(j,$),g>j&&f(j,g),g=j,`${E}${$}${e}${P}`}),n=ui(n,d,u.end.offset,m)}return n}function pg(n,t,e){let i=ot("listItem",n).filter(o=>!e.isProtected(o.start.offset,o.start.offset+1));if(!i)return n;let r=/^((\d+[.)])|(- \[[ x]\]))/m,s=t;if(t=="consistent"){let o=i.length-1;for(;o>=0;){let l=n.substring(i[o].start.offset,i[o].end.offset);if(o--,!l.match(r)){s=l.charAt(0);break}}if(o==-1)return n}let a=[];for(let o of i)n.substring(o.start.offset,o.end.offset).match(r)||a.push({startIndex:o.start.offset,endIndex:o.start.offset+1,value:s});return J(n,a)}function fg(n,t){let e=ot("blockquote",n),i=new Map;for(let r of e){let s=r.end.offset;for(;s<n.length-1&&n.charAt(s)!==`
`;)s++;i.set(r,t(n.substring(r.start.offset,s),r.start.offset))}for(let r of e){let s=i.get(r),a=r.end.offset;for(;a<n.length-1&&n.charAt(a)!==`
`;)a++;let o=n.substring(r.start.offset,a);o=s(o),n=ui(n,r.start.offset,a,o)}return n}function hg(n,t,e){let i=e.projection(),r=i.text,s=kr("math",i),a=new RegExp("^(\\${"+t+",})(\\n*)"),o=new RegExp("(\\n*)(\\${"+t+",})([^\\$]*)$");for(let l of s){let c=r.substring(l.startIndex,l.endIndex),u=Qx(c,t,l.startIndex);for(let d of u)r=Gh(r,d.startIndex,d.endIndex,a,o)}s=og(i,r);for(let l of s)r.substring(l.startIndex,l.endIndex).startsWith("$".repeat(t))&&(r=Gh(r,l.startIndex,l.endIndex,a,o));return vr(i,r)}function Qx(n,t,e){let i="$".repeat(t),r=t;for(;n.charAt(r)==="$";)i+="$",r++;let s=[],a=Tt(n,i);if(a<=1)return[];if(a===2)return s.unshift({startIndex:e,endIndex:e+n.length}),s;a===3&&s.unshift({startIndex:e,endIndex:e+n.indexOf(i,i.length)+i.length}),a%2===1&&a--;let o=e,l=i.length;for(;a>2;){let c=n.indexOf(i,l)+i.length;s.unshift({startIndex:o,endIndex:e+c}),o=e+c+1,l=c+1,a-=2}return s.unshift({startIndex:e+n.indexOf(i,l),endIndex:e+n.length}),s}function Gh(n,t,e,i,r){let s=n.substring(pi(n,t),t)??"",[a]=ur(s,s.length),o=n.substring(pi(n,e),e)??"",l=n.substring(t,e),c=kg.test(s.trim()),u=!1;for(l=l.replace(i,(d,m,p="")=>{let h="";return!c&&s.trim()!=""?(h+=`
`,u=!0):c&&!uu.test(s)&&(h+=`
`+a,u=!0),h+=m+`
`,p===""&&c&&(h+=a),h}),l=l.replace(r,(d,m="",p,h)=>{let f=m==="";return f&&c&&uu.test(o.trim())?d:f&&c?`
`+a+p+h:`
`+p+h});u&&t>0;){let d=n[t-1];if(d!==" "&&d!==" ")break;t--}return ui(n,t,e,l)}function fi(n){let t=[...n.matchAll(vg)],e=[];for(let i of t){let r=pi(n,i.index);if(r===0)continue;let s=pi(n,r-1),a=i[0],o=n.substring(r,i.index+a.length);if(Jx(o,a))continue;let l=s,c=n.substring(s,r-1);if(!a.includes("|")&&!c.includes("|"))continue;c=c.replace(mu,h=>(l+=h.length-1,""));let u=a.replace(mu,"");if(c.endsWith("|")&&(c=c.slice(0,-1)),u.endsWith("|")&&(u=u.slice(0,-1)),Qh(c)!==Qh(u))continue;if(s!==0){let h=pi(n,s-1),f=n.substring(h,s-1);if(f.startsWith("|")||f.endsWith("|"))continue}let d=i.index+i[0].length;if(d>=n.length-1){e.push({startIndex:l,endIndex:n.length});continue}let m=n.substring(d+1).split(`
`),p=0;for(;p<m.length&&Ag.test(m[p]);)d+=m[p].length+1,p++;e.push({startIndex:l,endIndex:d})}return e.reverse()}function Jx(n,t){if(n.trim()===""||t.includes("||"))return!0;let e=n.replace(t,"");return/[^\s>]/.test(e)}function Qh(n){let t=!1,e=0,i=0,r;for(let s=0;s<n.length;s++)r=n[s],r==="\\"?(e++,t=e%2==1):(e=0,r==="|"&&!t&&i++,t=!1);return i}function gg(n){let t=0,e=[],i=[...n.matchAll(wg)];if(!i||i.length===0)return e;let r=[...n.matchAll(xg)];return i.forEach(s=>{t=s.index;let a=!1,o=n.length-1;for(;r&&r.length!==0&&!a;)if(r[0].index<=t)r.shift();else{a=!0;let l=r[0];o=l.index+l[0].length}e.push({startIndex:t,endIndex:o}),!r||r.length}),e.reverse()}function yg(n,t,e){let i=ot("code",n);for(let r of i){let s=n.substring(r.start.offset,r.end.offset);if(!s.startsWith("```")||s.substring(3,s.indexOf(`
`)).trim()!=="")continue;let o=r.start.offset+3;e.isProtected(o,o)||(n=ui(n,o,o,t))}return n}function bg(n){let t=ot("link",n),e=[];for(let i of t)n.substring(i.start.offset,i.end.offset).match(Ar)||(i=Xx(n,i),!eL(n,i)&&e.push(Zx(n,i)));return e.push(...Hx(n)),e.sort((i,r)=>r.start.offset-i.start.offset),e}function Zx(n,t){let e=t.end.offset;for(;e>t.start.offset;){let i=n[e-1];if(!Sg.test(i))break;e--}return e===t.end.offset?t:{...t,end:{...t.end,offset:e}}}function Xx(n,t){let e="mailto:",i=t.start.offset;if(i<e.length||n.substring(i-e.length,i)!==e)return t;let r=i-e.length;return{start:{...t.start,offset:r,column:t.start.column-e.length},end:t.end}}function eL(n,t){for(let e=t.start.offset-1;e>=0;e--){let i=n[e];if(i===void 0||i.charCodeAt(0)>127||/\s/.test(i))return!1;if(i===":"&&e>0)return n[e-1]!==":"}return!1}var cn=/^([ \t]*)(#+)([ \t]+)([^\n\r]*?)([ \t]+#+)?$/gm,Eg=`^XXX\\.*?
(?:((?:.|
)*?)
)?XXX(?=\\s|$)$`,Ze=/^---\n((?:(((?!---)(?:.|\n)*?)\n)?))---(?=\n|$)/,tL=Eg.replaceAll("X","`"),nL=Eg.replaceAll("X","~"),iL=`^(( |( {4})).*
)+`,FN=new RegExp(`${tL}|${nL}|${iL}`,"gm"),pl=/(!?)\[{2}([^\][\n|]+)(\|([^\][\n|]+))?(\|([^\][\n|]+))?\]{2}/g,Ar=/(!?)\[([^[]*)\](\(.*\))/g,fl=/(\s|^)(#(?=\d*[\p{L}\-_/\p{Emoji_Presentation}])[\p{L}\-_\d/\p{Emoji_Presentation}]+)/gu,Tg=/^(?=\d*[\p{L}\-_/\p{Emoji_Presentation}])[\p{L}\-_\d/\p{Emoji_Presentation}]+$/u,Mg=/^%%\n[^%]*\n%%/gm,qa=/[,\s]+/,fu=/\S+/g,hl=/(\. ?){2}\./g,Wa="\\s*(>\\s*)*",uu=/^ {0,3}(>( |\t)*)+\$*?$/m,kg=/^\s*(>\s*)+/m,vg=/(\|? *:?-{1,}:? *\|?)(\| *:?-{1,}:? *\|?)*( |\t)*$/gm,mu=/^(((?:>[ \t]*)+)|([ ]{0,3}))\|/m,Ag=/[^\n]*?\|[^\n]*?(\n|$)/m,Og=/(([a-z\-0-9]+:)\/{2,3})([^\s/?#]*[^\s")'.?!/]|[/])?(([/?#][^\s")']*[^\s")'.?!])|[/])?/gi,Jr=/(?:(?:(?:[a-z]+:)?\/\/)|www\.)(?:localhost|(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?:(?:[a-fA-F\d]{1,4}:){7}(?:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,2}|:)|(?:[a-fA-F\d]{1,4}:){4}(?:(?::[a-fA-F\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,3}|:)|(?:[a-fA-F\d]{1,4}:){3}(?:(?::[a-fA-F\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,4}|:)|(?:[a-fA-F\d]{1,4}:){2}(?:(?::[a-fA-F\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,5}|:)|(?:[a-fA-F\d]{1,4}:){1}(?:(?::[a-fA-F\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?|(?:(?:[a-z0-9][-_]*)*[a-z0-9]+)(?:\.(?:[a-z0-9]-*)*[a-z0-9]+)*(?:\.(?:[a-z]{2,})))(?::\d{2,5})?(?:(?:[/?#][a-z0-9-_%/&=?$.+~:!*‘(,#@]*[a-z0-9-%_/$+~:!*‘(,])|[/])?/gi,BN=new RegExp("^"+Jr.source+"$","si"),Cg=/<a[\s]+([^>]+)>((?:.(?!<\/a>))*.)<\/a>/g,Ig=/[\p{L}\p{N}\p{Pc}\p{M}\-'’`]+/gu,Rg=/&[^\s]+;$/mi,wg=Kg(!0),xg=Kg(!1),Ng=/[“”„«»]/g,Fg=/[‘’‚‹›]/g,Bg=/<%[^]*?%>/g,wr="\\[.\\]",bi=new RegExp(`^${wr}`),Dg=new RegExp(`^${Wa}- ${wr} `),gl=new RegExp(`^\\s*- ${wr} `),ul=new RegExp(`^\\s*(- |\\* |\\+ |\\d+[.)] |- (${wr}) )`,"m"),ml=/^(\[\^[^\]]*\]) ?([,.;!:?])/gm,Lg=/^ ?\[![^\s]*\]/m,Qo=/^(>\s*)+\[![^\s]*\]/m,Ca=/^\n?(>\s*)+((```)|(~~~))/m,hu=RegExp(/\p{L}/,"u"),Zr=/(\n([\t\v\f\r \u00a0\u2000-\u200b\u2028-\u2029\u3000]+)?){2,}\n/g,Sg=/\p{Script=Han}|[,。!?;:、()[]【】「」『』“”‘’《》〈〉〔〕〖〗〘〙〚〛…—~¥﹁﹂﹃﹄﹏]/u;function ft(n){return n.replace(/\$/g,"$$$$")}function Mt(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Yg(n){let t=n.match(pl);if(t){for(let e of t)if(e.includes("|")){let i=e.indexOf("|"),r=e.substring(0,i+1)+e.substring(i+1,e.length-2).trim()+"]]";n=n.replace(e,r)}}return n}function _g(n){let t=fi(n);if(t.length===0)return n;for(let e of t)n=mi(n,e.startIndex,e.endIndex);return n}function yl(n,t){let e=[...n.matchAll(/^#[^\S\r\n\u2028\u2029]+(.*)/gm)].find(i=>!t.isProtected(i.index,i.index+i[0].length-i[1].length));if(e&&e[1]){let i=e[1];return i=i.replaceAll(pl,(r,s,a,o)=>o!=null?o.replace("|",""):a),i=i.replaceAll(Ar,"$2"),th(i)}return""}function Kg(n){let t="(?:<!-{2,}|%%) *linter-{ENDING_TEXT} *(?:-{2,}>|%%)",e="";return n?e+="disable":e+="enable",new RegExp(t.replace("{ENDING_TEXT}",e),"g")}var bl=Symbol.for("yaml.alias"),kl=Symbol.for("yaml.document"),dn=Symbol.for("yaml.map"),gu=Symbol.for("yaml.pair"),Ot=Symbol.for("yaml.scalar"),Vn=Symbol.for("yaml.seq"),ct=Symbol.for("yaml.node.type"),un=n=>!!n&&typeof n=="object"&&n[ct]===bl,mn=n=>!!n&&typeof n=="object"&&n[ct]===kl,ht=n=>!!n&&typeof n=="object"&&n[ct]===dn,ce=n=>!!n&&typeof n=="object"&&n[ct]===gu,ne=n=>!!n&&typeof n=="object"&&n[ct]===Ot,pn=n=>!!n&&typeof n=="object"&&n[ct]===Vn;function pe(n){if(n&&typeof n=="object")switch(n[ct]){case dn:case Vn:return!0}return!1}function ue(n){if(n&&typeof n=="object")switch(n[ct]){case bl:case dn:case Ot:case Vn:return!0}return!1}var vl=n=>(ne(n)||pe(n))&&!!n.anchor;var gt=Symbol("break visit"),Pg=Symbol("skip children"),Cn=Symbol("remove node");function Ut(n,t){let e=zg(t);mn(n)?Xr(null,n.contents,e,Object.freeze([n]))===Cn&&(n.contents=null):Xr(null,n,e,Object.freeze([]))}Ut.BREAK=gt;Ut.SKIP=Pg;Ut.REMOVE=Cn;function Xr(n,t,e,i){let r=qg(n,t,e,i);if(ue(r)||ce(r))return Wg(n,i,r),Xr(n,r,e,i);if(typeof r!="symbol"){if(pe(t)){i=Object.freeze(i.concat(t));for(let s=0;s<t.items.length;++s){let a=Xr(s,t.items[s],e,i);if(typeof a=="number")s=a-1;else{if(a===gt)return gt;a===Cn&&(t.items.splice(s,1),s-=1)}}}else if(ce(t)){i=Object.freeze(i.concat(t));let s=Xr("key",t.key,e,i);if(s===gt)return gt;s===CnLine truncated
`)}};In.defaultYaml={explicit:!1,version:"1.2"};In.defaultTags={"!!":"tag:yaml.org,2002:"};function wl(n){if(/[\x00-\x19\s,[\]{}]/.test(n)){let e=`Anchor must not contain whitespace or control characters: ${JSON.stringify(n)}`;throw new Error(e)}return!0}function yu(n){let t=new Set;return Ut(n,{Value(e,i){i.anchor&&t.add(i.anchor)}}),t}function bu(n,t){for(let e=1;;++e){let i=`${n}${e}`;if(!t.has(i))return i}}function jg(n,t){let e=[],i=new Map,r=null;return{onAnchor:s=>{e.push(s),r??(r=yu(n));let a=bu(t,r);return r.add(a),a},setAnchors:()=>{for(let s of e){let a=i.get(s);if(typeof a=="object"&&a.anchor&&(ne(a.node)||pe(a.node)))a.node.anchor=a.anchor;else{let o=new Error("Failed to resolve repeated object (this should not happen)");throw o.source=s,o}}},sourceObjects:i}}function ki(n,t,e,i){if(i&&typeof i=="object")if(Array.isArray(i))for(let r=0,s=i.length;r<s;++r){let a=i[r],o=ki(n,i,String(r),a);o===void 0?delete i[r]:o!==a&&(i[r]=o)}else if(i instanceof Map)for(let r of Array.from(i.keys())){let s=i.get(r),a=ki(n,i,r,s);a===void 0?i.delete(r):a!==s&&i.set(r,a)}else if(i instanceof Set)for(let r of Array.from(i)){let s=ki(n,i,r,r);s===void 0?i.delete(r):s!==r&&(i.delete(r),i.add(s))}else for(let[r,s]of Object.entries(i)){let a=ki(n,i,r,s);a===void 0?delete i[r]:a!==s&&(i[r]=a)}return n.call(t,e,i)}function _e(n,t,e){if(Array.isArray(n))return n.map((i,r)=>_e(i,String(r),e));if(n&&typeof n.toJSON=="function"){if(!e||!vl(n))return n.toJSON(t,e);let i={aliasCount:0,count:1,res:void 0};e.anchors.set(n,i),e.onCreate=s=>{i.res=s,delete e.onCreate};let r=n.toJSON(t,e);return e.onCreate&&e.onCreate(r),r}return typeof n=="bigint"&&!e?.keep?Number(n):n}var vi=class{constructor(t){Object.defineProperty(this,ct,{value:t})}clone(){let t=Object.create(Object.getPrototypeOf(this),Object.getOwnPropertyDescriptors(this));return this.range&&(t.range=this.range.slice()),t}toJS(t,{mapAsMap:e,maxAliasCount:i,onAnchor:r,reviver:s}={}){if(!mn(t))throw new TypeError("A document argument is required");let a={anchors:new Map,doc:t,keep:!0,mapAsMap:e===!0,mapKeyWarned:!1,maxAliasCount:typeof i=="number"?i:100},o=_e(this,"",a);if(typeof r=="function")for(let{count:l,res:c}of a.anchors.values())r(c,l);return typeof s=="function"?ki(s,{"":o},"",o):o}};var Gn=class extends vi{constructor(t){super(bl),this.source=t,Object.defineProperty(this,"tag",{set(){throw new Error("Alias nodes cannot have tags")}})}resolve(t,e){if(e?.maxAliasCount===0)throw new ReferenceError("Alias resolution is disabled");let i;e?.aliasResolveCache?i=e.aliasResolveCache:(i=[],Ut(t,{Node:(s,a)=>{(un(a)||vl(a))&&i.push(a)}}),e&&(e.aliasResolveCache=i));let r;for(let s of i){if(s===this)break;s.anchor===this.source&&(r=s)}if(r&&e){let{anchors:s,doc:a,maxAliasCount:o}=e,l=s.get(r);if(l||(_e(r,null,e),l=s.get(r)),l?.res===void 0){let c="This should not happen: Alias anchor was not resolved?";throw new ReferenceError(c)}if(o>=0&&(l.count+=1,l.aliasCount===0&&(l.aliasCount=xl(a,r,s)),l.count*l.aliasCount>o)){let c="Excessive alias count indicates a resource exhaustion attack";throw new ReferenceError(c)}}return r}toJSON(t,e){if(!e)return{source:this.source};let i=this.resolve(e.doc,e);if(!i){let r=`Unresolved alias (the anchor must be set before the alias): ${this.source}`;throw new ReferenceError(r)}return e.anchors.get(i).res}toString(t,e,i){let r=`*${this.source}`;if(t){if(wl(this.source),t.options.verifyAliasOrder&&!t.anchors.has(this.source)){let s=`Unresolved alias (the anchor must be set before the alias): ${this.source}`;throw new Error(s)}if(t.implicitKey)return`${r} `}return r}};function xl(n,t,e){if(un(t)){let i=t.resolve(n),r=e&&i&&e.get(i);return r?r.count*r.aliasCount:0}else if(pe(t)){let i=0;for(let r of t.items){let s=xl(n,r,e);s>i&&(i=s)}return i}else if(ce(t)){let i=xl(n,t.key,e),r=xl(n,t.value,e);return Math.max(i,r)}return 1}var Ll=n=>!n||typeof n!="function"&&typeof n!="object",W=class extends vi{constructor(t){super(Ot),this.value=t}toJSON(t,e){return e?.keep?this.value:_e(this.value,t,e)}toString(){return String(this.value)}};W.BLOCK_FOLDED="BLOCK_FOLDED";W.BLOCK_LITERAL="BLOCK_LITERAL";W.PLAIN="PLAIN";W.QUOTE_DOUBLE="QUOTE_DOUBLE";W.QUOTE_SINGLE="QUOTE_SINGLE";var aL="tag:yaml.org,2002:";function oL(n,t,e){if(t){let i=e.filter(s=>s.tag===t),r=i.find(s=>!s.format)??i[0];if(!r)throw new Error(`Tag ${t} not found`);return r}return e.find(i=>i.identify?.(n)&&!i.format)}function Qn(n,t,e){if(mn(n)&&(n=n.contents),ue(n))return n;if(ce(n)){let d=e.schema[dn].createNode?.(e.schema,null,e);return d.items.push(n),d}(n instanceof String||n instanceof Number||n instanceof Boolean||typeof BigInt<"u"&&n instanceof BigInt)&&(n=n.valueOf());let{aliasDuplicateObjects:i,onAnchor:r,onTagObj:s,schema:a,sourceObjects:o}=e,l;if(i&&n&&typeof n=="object"){if(l=o.get(n),l)return l.anchor??(l.anchor=r(n)),new Gn(l.anchor);l={anchor:null,node:null},o.set(n,l)}t?.startsWith("!!")&&(t=aL+t.slice(2));let c=oL(n,t,a.tags);if(!c){if(n&&typeof n.toJSON=="function"&&(n=n.toJ Line truncated
`)?Ht(e,t):e.includes(`
`)?`
`+Ht(e,t):(n.endsWith(" ")?"":" ")+e;var ku="flow",Sl="block",Ua="quoted";function Ha(n,t,e="flow",{indentAtStart:i,lineWidth:r=80,minContentWidth:s=20,onFold:a,onOverflow:o}={}){if(!r||r<0)return n;r<s&&(s=0);let l=Math.max(1+s,1+r-t.length);if(n.length<=l)return n;let c=[],u={},d=r-t.length;typeof i=="number"&&(i>r-Math.max(2,s)?c.push(0):d=r-i);let m,p,h=!1,f=-1,g=-1,b=-1;e===Sl&&(f=Hg(n,f,t.length),f!==-1&&(d=f+l));for(let x;x=n[f+=1];){if(e===Ua&&x==="\\"){switch(g=f,n[f+1]){case"x":f+=3;break;case"u":f+=5;break;case"U":f+=9;break;default:f+=1}b=f}if(x===`
`)e===Sl&&(f=Hg(n,f,t.length)),d=f+t.length+l,m=void 0;else{if(x===" "&&p&&p!==" "&&p!==`
`&&p!==" "){let E=n[f+1];E&&E!==" "&&E!==`
`&&E!==" "&&(m=f)}if(f>=d)if(m)c.push(m),d=m+l,m=void 0;else if(e===Ua){for(;p===" "||p===" ";)p=x,x=n[f+=1],h=!0;let E=f>b+1?f-2:g-1;if(u[E])return n;c.push(E),u[E]=!0,d=E+l,m=void 0}else h=!0}p=x}if(h&&o&&o(),c.length===0)return n;a&&a();let k=n.slice(0,c[0]);for(let x=0;x<c.length;++x){let E=c[x],C=c[x+1]||n.length;E===0?k=`
${t}${n.slice(0,C)}`:(e===Ua&&u[E]&&(k+=`${n[E]}\\`),k+=`
${t}${n.slice(E+1,C)}`)}return k}function Hg(n,t,e){let i=t,r=t+1,s=n[r];for(;s===" "||s===" ";)if(t<r+e)s=n[++t];else{do s=n[++t];while(s&&s!==`
`);i=t,r=t+1,s=n[r]}return i}var Tl=(n,t)=>({indentAtStart:t?n.indent.length:n.indentAtStart,lineWidth:n.options.lineWidth,minContentWidth:n.options.minContentWidth}),Ml=n=>/^(%|---|\.\.\.)/m.test(n);function lL(n,t,e){if(!t||t<0)return!1;let i=t-e,r=n.length;if(r<=i)return!1;for(let s=0,a=0;s<r;++s)if(n[s]===`
`){if(s-a>i)return!0;if(a=s+1,r-a<=i)return!1}return!0}function $a(n,t){let e=JSON.stringify(n);if(t.options.doubleQuotedAsJSON)return e;let{implicitKey:i}=t,r=t.options.doubleQuotedMinMultiLineLength,s=t.indent||(Ml(n)?" ":""),a="",o=0;for(let l=0,c=e[l];c;c=e[++l])if(c===" "&&e[l+1]==="\\"&&e[l+2]==="n"&&(a+=e.slice(o,l)+"\\ ",l+=1,o=l,c="\\"),c==="\\")switch(e[l+1]){case"u":{a+=e.slice(o,l);let u=e.substr(l+2,4);switch(u){case"0000":a+="\\0";break;case"0007":a+="\\a";break;case"000b":a+="\\v";break;case"001b":a+="\\e";break;case"0085":a+="\\N";break;case"00a0":a+="\\_";break;case"2028":a+="\\L";break;case"2029":a+="\\P";break;default:u.substr(0,2)==="00"?a+="\\x"+u.substr(2):a+=e.substr(l,6)}l+=5,o=l+1}break;case"n":if(i||e[l+2]==='"'||e.length<r)l+=1;else{for(a+=e.slice(o,l)+`
`;e[l+2]==="\\"&&e[l+3]==="n"&&e[l+4]!=='"';)a+=`
`,l+=2;a+=s,e[l+2]===" "&&(a+="\\"),l+=1,o=l+1}break;default:l+=1}return a=o?a+e.slice(o):e,i?a:Ha(a,s,Ua,Tl(t,!1))}function vu(n,t){if(t.options.singleQuote===!1||t.implicitKey&&n.includes(`
`)||/[ \t]\n|\n[ \t]/.test(n))return $a(n,t);let e=t.indent||(Ml(n)?" ":""),i="'"+n.replace(/'/g,"''").replace(/\n+/g,`$&
${e}`)+"'";return t.implicitKey?i:Ha(i,e,ku,Tl(t,!1))}function is(n,t){let{singleQuote:e}=t.options,i;if(e===!1)i=$a;else{let r=n.includes('"'),s=n.includes("'");r&&!s?i=vu:s&&!r?i=$a:i=e?vu:$a}return i(n,t)}var Au;try{Au=new RegExp(`(^|(?<!
))
+(?!
|$)`,"g")}catch{Au=/\n+(?!\n|$)/g}function El({comment:n,type:t,value:e},i,r,s){let{blockQuote:a,commentString:o,lineWidth:l}=i.options;if(!a||/\n[\t ]+$/.test(e))return is(e,i);let c=i.indent||(i.forceBlockIndent||Ml(e)?" ":""),u=a==="literal"?!0:a==="folded"||t===W.BLOCK_FOLDED?!1:t===W.BLOCK_LITERAL?!0:!lL(e,l,c.length);if(!e)return u?`|
`:`>
`;let d,m;for(m=e.length;m>0;--m){let C=e[m-1];if(C!==`
`&&C!==" "&&C!==" ")break}let p=e.substring(m),h=p.indexOf(`
`);h===-1?d="-":e===p||h!==p.length-1?(d="+",s&&s()):d="",p&&(e=e.slice(0,-p.length),p[p.length-1]===`
`&&(p=p.slice(0,-1)),p=p.replace(Au,`$&${c}`));let f=!1,g,b=-1;for(g=0;g<e.length;++g){let C=e[g];if(C===" ")f=!0;else if(C===`
`)b=g;else break}let k=e.substring(0,b<g?b+1:g);k&&(e=e.substring(k.length),k=k.replace(/\n+/g,`$&${c}`));let E=(f?c?"2":"1":"")+d;if(n&&(E+=" "+o(n.replace(/ ?[\r\n]+/g," ")),r&&r()),!u){let C=e.replace(/\n+/g,`
$&`).replace(/(?:^|\n)([\t ].*)(?:([\n\t ]*)\n(?![\n\t ]))?/g,"$1$2").replace(/\n+/g,`$&${c}`),M=!1,N=Tl(i,!0);a!=="folded"&&t!==W.BLOCK_FOLDED&&(N.onOverflow=()=>{M=!0});let F=Ha(`${k}${C}${p}`,c,Sl,N);if(!M)return`>${E}
${c}${F}`}return e=e.replace(/\n+/g,`$&${c}`),`|${E}
${c}${k}${e}${p}`}function cL(n,t,e,i){let{type:r,value:s}=n,{actualString:a,implicitKey:o,indent:l,indentStep:c,inFlow:u}=t;if(o&&s.includes(`
`)||u&&/[[\]{},]/.test(s))return is(s,t);if(/^[\n\t ,[\]{}#&*!|>'"%@`]|^[?-]$|^[?-][ \t]|[\n:][ \t]|[ \t]\n|[\n\t ]#|[\n\t :]$/.test(s))return o||u||!s.includes(`
`)?is(s,t):El(n,t,e,i);if(!o&&!u&&r!==W.PLAIN&&s.includes(`
`))return El(n,t,e,i);if(Ml(s)){if(l==="")return t.forceBlockIndent=!0,El(n,t,e,i);if(o&&l===c)return is(s,t)}let d=s.replace(/\n+/g,`$&
${l}`);if(a){let m=f=>f.default&&f.tag!=="tag:yaml.org,2002:str"&&f.test?.test(d),{compat:p,tags:h}=t.doc.schema;if(h.some(m)||p?.some(m))return is(s,t)}return o?d:Ha(d,l,ku,Tl(t,!1))}function Jn(n,t,e,i){let{implicitKey:r,inFlow:s}=t,a=typeof n.value=="string"?n:Object.assign({},n,{value:String(n.value)}),{type:o}=n;o!==W.QUOTE_DOUBLE&&/[\x00-\x08\x0b-\x1f\x7f-\x9f\u{D800}-\u{DFFF}]/u.test(a.value)&&(o=W.QUOTE_DOUBLE);let l=u=>{switch(u){case W.BLOCK_FOLDED:case W.BLOCK_LITERAL:return r||s?is(a.value,t):El(a,t,e,i);case W.QUOTE_DOUBLE:return $a(a.value,t);case W.QUOTE_SINGLE:return vu(a.value,t);case W.PLAIN:return cL(a,t,e,i);default:return null}},c=l(o);if(c===null){let{defaultKeyType:u,defaultStringType:d}=t.options,m=r&&u||d;if(c=l(m),c===null)throw new Error(`Unsupported default string type ${m}`)}return c}function Ol(n,t){let e=Object.assign({blockQuote:!0,commentString:Ug,defaultKeyType:null,defaultStringType:"PLAIN",directives:null,doubleQuotedAsJSON:!1,doubleQuotedMinMultiLineLength:40,falseStr:"false",flowCollectionPadding:!0,indentSeq:!0,lineWidth:80,minContentWidth:20,nullStr:"null",simpleKeys:!1,singleQuote:null,trailingComma:!1,trueStr:"true",verifyAliasOrder:!0},n.schema.toStringOptions,t),i;switch(e.collectionStyle){case"block":i=!1;break;case"flow":i=!0;break;default:i=null}return{anchors:new Set,doc:n,flowCollectionPadding:e.flowCollectionPadding?" ":"",indent:"",indentStep:typeof e.indent=="number"?" ".repeat(e.indent):" ",inFlow:i,options:e}}function dL(n,t){if(t.tag){let r=n.filter(s=>s.tag===t.tag);if(r.length>0)return r.find(s=>s.format===t.format)??r[0]}let e,i;if(ne(t)){i=t.value;let r=n.filter(s=>s.identify?.(i));if(r.length>1){let s=r.filter(a=>a.test);s.length>0&&(r=s)}e=r.find(s=>s.format===t.format)??r.find(s=>!s.format)}else i=t,e=n.find(r=>r.nodeClass&&i instanceof r.nodeClass);if(!e){let r=i?.constructor?.name??(i===null?"null":typeof i);throw new Error(`Tag not resolved for ${r} value`)}return e}function uL(n,t,{anchors:e,doc:i}){if(!i.directives)return"";let r=[],s=(ne(n)||pe(n))&&n.anchor;s&&wl(s)&&(e.add(s),r.push(`&${s}`));let a=n.tag??(t.default?null:t.tag);return a&&r.push(i.directives.tagString(a)),r.join(" ")}function Zn(n,t,e,i){if(ce(n))return n.toString(t,e,i);if(un(n)){if(t.doc.directives)return n.toString(t);if(t.resolvedAliases?.has(n))throw new TypeError("Cannot stringify circular structure without alias nodes");t.resolvedAliases?t.resolvedAliases.add(n):t.resolvedAliases=new Set([n]),n=n.resolve(t.doc)}let r,s=ue(n)?n:t.doc.createNode(n,{onTagObj:l=>r=l});r??(r=dL(t.doc.schema.tags,s));let a=uL(s,r,t);a.length>0&&(t.indentAtStart=(t.indentAtStart??0)+a.length+1);let o=typeof r.stringify=="function"?r.stringify(s,t,e,i):ne(s)?Jn(s,t,e,i):s.toString(t,e,i);return a?ne(s)||o[0]==="{"||o[0]==="["?`${a} ${o}`:`${a}
${t.indent}${o}`:o}function $g({key:n,value:t},e,i,r){let{allNullValues:s,doc:a,indent:o,indentStep:l,options:{commentString:c,indentSeq:u,simpleKeys:d}}=e,m=ue(n)&&n.comment||null;if(d){if(m)throw new Error("With simple keys, key nodes cannot have comments");if(pe(n)||!ue(n)&&typeof n=="object"){let N="With simple keys, collection cannot be used as a key value";throw new Error(N)}}let p=!d&&(!n||m&&t==null&&!e.inFlow||pe(n)||(ne(n)?n.type===W.BLOCK_FOLDED||n.type===W.BLOCK_LITERAL:typeof n=="object"));e=Object.assign({},e,{allNullValues:!1,implicitKey:!p&&(d||!s),indent:o+l});let h=!1,f=!1,g=Zn(n,e,()=>h=!0,()=>f=!0);if(!p&&!e.inFlow&&g.length>1024){if(d)throw new Error("With simple keys, single line scalar must not span more than 1024 characters");p=!0}if(e.inFlow){if(s||t==null)return h&&i&&i(),g===""?"?":p?`? ${g}`:g}else if(s&&!d||t==null&&p)return g=`? ${g}`,m&&!h?g+=Rn(g,e.indent,c(m)):f&&r&&r(),g;h&&(m=null),p?(m&&(g+=Rn(g,e.indent,c(m))),g=`? ${g}
${o}:`):(g=`${g}:`,m&&(g+=Rn(g,e.indent,c(m))));let b,k,x;ue(t)?(b=!!t.spaceBefore,k=t.commentBefore,x=t.comment):(b=!1,k=null,x=null,t&&typeof t=="object"&&(t=a.createNode(t))),e.implicitKey=!1,!p&&!m&&ne(t)&&(e.indentAtStart=g.length+1),f=!1,!u&&l.length>=2&&!e.inFlow&&!p&&pn(t)&&!t.flow&&!t.tag&&!t.anchor&&(e.indent=e.indent.substring(2));let E=!1,C=Zn(t,e,()=>E=!0,()=>f=!0),M=" ";if(m||b||k){if(M=b?`
`:"",k){let N=c(k);M+=`
${Ht(N,e.indent)}`}C===""&&!e.inFlow?M===`
`&&x&&(M=`
`):M+=`
${e.indent}`}else if(!p&&pe(t)){let N=C[0],F=C.indexOf(`
`),P=F!==-1,q=e.inFlow??t.flow??t.items.length===0;if(P||!q){let $=!1;if(P&&(N==="&"||N==="!")){let j=C.indexOf(" ");N==="&"&&j!==-1&&j<F&&C[j+1]==="!"&&(j=C.indexOf(" ",j+1)),(j===-1||F<j)&&($=!0)}$||(M=`
${e.indent}`)}}else(C===""||C[0]===`
`)&&(M="");return g+=M+C,e.inFlow?E&&i&&i():x&&!E?g+=Rn(g,e.indent,c(x)):f&&r&&r(),g}function Cl(n,t){(n==="debug"||n==="warn")&&console.warn(t)}var Il="<<",fn={identify:n=>n===Il||typeof n=="symbol"&&n.description===Il,default:"key",tag:"tag:yaml.org,2002:merge",test:/^<<$/,resolve:()=>Object.assign(new W(Symbol(Il)),{addToJSMap:xu}),stringify:()=>Il},Vg=(n,t)=>(fn.identify(t)||ne(t)&&(!t.type||t.type===W.PLAIN)&&fn.identify(t.value))&&n?.doc.schema.tags.some(e=>e.tag===fn.tag&&e.default);function xu(n,t,e){let i=Gg(n,e);if(pn(i))for(let r of i.items)wu(n,t,r);else if(Array.isArray(i))for(let r of i)wu(n,t,r);else wu(n,t,i)}function wu(n,t,e){let i=Gg(n,e);if(!ht(i))throw new Error("Merge sources must be maps or map aliases");let r=i.toJSON(null,n,Map);for(let[s,a]of r)t instanceof Map?t.has(s)||t.set(s,a):t instanceof Set?t.add(s):Object.prototype.hasOwnProperty.call(t,s)||Object.defineProperty(t,s,{value:a,writable:!0,enumerable:!0,configurable:!0});return t}function Gg(n,t){return n&&un(t)?t.resolve(n.doc,n):t}function Rl(n,t,{key:e,value:i}){if(ue(e)&&e.addToJSMap)e.addToJSMap(n,t,i);else if(Vg(n,e))xu(n,t,i);else{let r=_e(e,"",n);if(t instanceof Map)t.set(r,_e(i,r,n));else if(t instanceof Set)t.add(r);else{let s=mL(e,r,n),a=_e(i,s,n);s in t?Object.defineProperty(t,s,{value:a,writable:!0,enumerable:!0,configurable:!0}):t[s]=a}}return t}function mL(n,t,e){if(t===null)return"";if(typeof t!="object")return String(t);if(ue(n)&&e?.doc){let i=Ol(e.doc,{});i.anchors=new Set;for(let s of e.anchors.keys())i.anchors.add(s.anchor);i.inFlow=!0,i.inStringifyKey=!0;let r=n.toString(i);if(!e.mapKeyWarned){let s=JSON.stringify(r);s.length>40&&(s=s.substring(0,36)+'..."'),Cl(e.doc.options.logLevel,`Keys with collection values will be stringified due to JS Object restrictions: ${s}. Set mapAsMap: true to use object keys.`),e.mapKeyWarned=!0}return r}return JSON.stringify(t)}function rs(n,t,e){let i=Qn(n,void 0,e),r=Qn(t,void 0,e);return new Ce(i,r)}var Ce=class n{constructor(t,e=null){Object.defineProperty(this,ct,{value:gu}),this.key=t,this.value=e}clone(t){let{key:e,value:i}=this;return ue(e)&&(e=e.clone(t)),ue(i)&&(i=i.clone(t)),new n(e,i)}toJSON(t,e){let i=e?.mapAsMap?new Map:{};return Rl(e,i,this)}toString(t,e,i){return t?.doc?$g(this,t,e,i):JSON.stringify(this)}};function Fl(n,t,e){return(t.inFlow??n.flow?fL:pL)(n,t,e)}function pL({comment:n,items:t},e,{blockItemPrefix:i,flowChars:r,itemIndent:s,onChompKeep:a,onComment:o}){let{indent:l,options:{commentString:c}}=e,u=Object.assign({},e,{indent:s,type:null}),d=!1,m=[];for(let h=0;h<t.length;++h){let f=t[h],g=null;if(ue(f))!d&&f.spaceBefore&&m.push(""),Nl(e,m,f.commentBefore,d),f.comment&&(g=f.comment);else if(ce(f)){let k=ue(f.key)?f.key:null;k&&(!d&&k.spaceBefore&&m.push(""),Nl(e,m,k.commentBefore,d))}d=!1;let b=Zn(f,u,()=>g=null,()=>d=!0);g&&(b+=Rn(b,s,c(g))),d&&g&&(d=!1),m.push(i+b)}let p;if(m.length===0)p=r.start+r.end;else{p=m[0];for(let h=1;h<m.length;++h){let f=m[h];p+=f?`
${l}${f}`:`
`}}return n?(p+=`
`+Ht(c(n),l),o&&o()):d&&a&&a(),p}function fL({items:n},t,{flowChars:e,itemIndent:i}){let{indent:r,indentStep:s,flowCollectionPadding:a,options:{commentString:o}}=t;i+=s;let l=Object.assign({},t,{indent:i,inFlow:!0,type:null}),c=!1,u=0,d=[];for(let h=0;h<n.length;++h){let f=n[h],g=null;if(ue(f))f.spaceBefore&&d.push(""),Nl(t,d,f.commentBefore,!1),f.comment&&(g=f.comment);else if(ce(f)){let k=ue(f.key)?f.key:null;k&&(k.spaceBefore&&d.push(""),Nl(t,d,k.commentBefore,!1),k.comment&&(c=!0));let x=ue(f.value)?f.value:null;x?(x.comment&&(g=x.comment),x.commentBefore&&(c=!0)):f.value==null&&k?.comment&&(g=k.comment)}g&&(c=!0);let b=Zn(f,l,()=>g=null);c||(c=d.length>u||b.includes(`
`)),h<n.length-1?b+=",":t.options.trailingComma&&(t.options.lineWidth>0&&(c||(c=d.reduce((k,x)=>k+x.length+2,2)+(b.length+2)>t.options.lineWidth)),c&&(b+=",")),g&&(b+=Rn(b,i,o(g))),d.push(b),u=d.length}let{start:m,end:p}=e;if(d.length===0)return m+p;if(!c){let h=d.reduce((f,g)=>f+g.length+2,2);c=t.options.lineWidth>0&&h>t.options.lineWidth}if(c){let h=m;for(let f of d)h+=f?`
${s}${r}${f}`:`
`;return`${h}
${r}${p}`}else return`${m}${a}${d.join(" ")}${a}${p}`}function Nl({indent:n,options:{commentString:t}},e,i,r){if(i&&r&&(i=i.replace(/^\n+/,"")),i){let s=Ht(t(i),n);e.push(s.trimStart())}}function Ai(n,t){let e=ne(t)?t.value:t;for(let i of n)if(ce(i)&&(i.key===t||i.key===e||ne(i.key)&&i.key.value===e))return i}var Me=class extends ts{static get tagName(){return"tag:yaml.org,2002:map"}constructor(t){super(dn,t),this.items=[]}static from(t,e,i){let{keepUndefined:r,replacer:s}=i,a=new this(t),o=(l,c)=>{if(typeof s=="function")c=s.call(e,l,c);else if(Array.isArray(s)&&!s.includes(l))return;(c!==void 0||r)&&a.items.push(rs(l,c,i))};if(e instanceof Map)for(let[l,c]of e)o(l,c);else if(e&&typeof e=="object")for(let l of Object.keys(e))o(l,e[l]);return typeof t.sortMapEntries=="function"&&a.items.sort(t.sortMapEntries),a}add(t,e){let i;ce(t)?i=t:!t||typeof t!="object"||!("key"in t)?i=new Ce(t,t?.value):i=new Ce(t.key,t.value);let r=Ai(this.items,i.key),s=this.schema?.sortMapEntries;if(r){if(!e)throw new Error(`Key ${i.key} already set`);ne(r.value)&&Ll(i.value)?r.value.value=i.value:r.value=i.value}else if(s){let a=this.items.findIndex(o=>s(i,o)<0);a===-1?this.items.push(i):this.items.splice(a,0,i)}else this.items.push(i)}delete(t){let e=Ai(this.items,t);return e?this.items.splice(this.items.indexOf(e),1).length>0:!1}get(t,e){let r=Ai(this.items,t)?.value;return(!e&&ne(r)?r.value:r)??void 0}has(t){return!!Ai(this.items,t)}set(t,e){this.add(new Ce(t,e),!0)}toJSON(t,e,i){let r=i?new i:e?.mapAsMap?new Map:{};e?.onCreate&&e.onCreate(r);for(let s of this.items)Rl(e,r,s);return r}toString(t,e,i){if(!t)return JSON.stringify(this);for(let r of this.items)if(!ce(r))throw new Error(`Map items must all be pairs; found ${JSON.stringify(r)} instead`);return!t.allNullValues&&this.hasAllNullValues(!1)&&(t=Object.assign({},t,{allNullValues:!0})),Fl(this,t,{blockItemPrefix:"",flowChars:{start:"{",end:"}"},itemIndent:t.indent||"",onChompKeep:i,onComment:e})}};var hn={collection:"map",default:!0,nodeClass:Me,tag:"tag:yaml.org,2002:map",resolve(n,t){return ht(n)||t("Expected a mapping for this tag"),n},createNode:(n,t,e)=>Me.from(n,t,e)};var Xe=class extends ts{static get tagName(){return"tag:yaml.org,2002:seq"}constructor(t){super(Vn,t),this.items=[]}add(t){this.items.push(t)}delete(t){let e=Bl(t);return typeof e!="number"?!1:this.items.splice(e,1).length>0}get(t,e){let i=Bl(t);if(typeof i!="number")return;let r=this.items[i];return!e&&ne(r)?r.value:r}has(t){let e=Bl(t);return typeof e=="number"&&e<this.items.length}set(t,e){let i=Bl(t);if(typeof i!="number")throw new Error(`Expected a valid index, not ${t}.`);let r=this.items[i];ne(r)&&Ll(e)?r.value=e:this.items[i]=e}toJSON(t,e){let i=[];e?.onCreate&&e.onCreate(i);let r=0;for(let s of this.items)i.push(_e(s,String(r++),e));return i}toString(t,e,i){return t?Fl(this,t,{blockItemPrefix:"- ",flowChars:{start:"[",end:"]"},itemIndent:(t.indent||"")+" ",onChompKeep:i,onComment:e}):JSON.stringify(this)}static from(t,e,i){let{replacer:r}=i,s=new this(t);if(e&&Symbol.iterator in Object(e)){let a=0;for(let o of e){if(typeof r=="function"){let l=e instanceof Set?o:String(a++);o=r.call(e,l,o)}s.items.push(Qn(o,void 0,i))}}return s}};function Bl(n){let t=ne(n)?n.value:n;return t&&typeof t=="string"&&(t=Number(t)),typeof t=="number"&&Number.isInteger(t)&&t>=0?t:null}var gn={collection:"seq",default:!0,nodeClass:Xe,tag:"tag:yaml.org,2002:seq",resolve(n,t){return pn(n)||t("Expected a sequence for this tag"),n},createNode:(n,t,e)=>Xe.from(n,t,e)};var wi={identify:n=>typeof n=="string",default:!0,tag:"tag:yaml.org,2002:str",resolve:n=>n,stringify(n,t,e,i){return t=Object.assign({actualString:!0},t),Jn(n,t,e,i)}};var xr={identify:n=>n==null,createNode:()=>new W(null),default:!0,tag:"tag:yaml.org,2002:null",test:/^(?:~|[Nn]ull|NULL)?$/,resolve:()=>new W(null),stringify:({source:n},t)=>typeof n=="string"&&xr.test.test(n)?n:t.options.nullStr};var Va={identify:n=>typeof n=="boolean",default:!0,tag:"tag:yaml.org,2002:bool",test:/^(?:[Tt]rue|TRUE|[Ff]alse|FALSE)$/,resolve:n=>new W(n[0]==="t"||n[0]==="T"),stringify({source:n,value:t},e){if(n&&Va.test.test(n)){let i=n[0]==="t"||n[0]==="T";if(t===i)return n}return t?e.options.trueStr:e.options.falseStr}};function et({format:n,minFractionDigits:t,tag:e,value:i}){if(typeof i=="bigint")return String(i);let r=typeof i=="number"?i:Number(i);if(!isFinite(r))return isNaN(r)?".nan":r<0?"-.inf":".inf";let s=Object.is(i,-0)?"-0":JSON.stringify(i);if(!n&&t&&(!e||e==="tag:yaml.org,2002:float")&&/^-?\d/.test(s)&&!s.includes("e")){let a=s.indexOf(".");a<0&&(a=s.length,s+=".");let o=t-(s.length-a-1);for(;o-- >0;)s+="0"}return s}var Dl={identify:n=>typeof n=="number",default:!0,tag:"tag:yaml.org,2002:float",test:/^(?:[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN)$/,resolve:n=>n.slice(-3).toLowerCase()==="nan"?NaN:n[0]==="-"?Number.NEGATIVE_INFINITY:Number.POSITIVE_INFINITY,stringify:et},Yl={identify:n=>typeof n=="number",default:!0,tag:"tag:yaml.org,2002:float",format:"EXP",test:/^ Line truncated
`:" ")}return Jn({comment:n,type:t,value:o},i,r,s)}};function Su(n,t){if(pn(n))for(let e=0;e<n.items.length;++e){let i=n.items[e];if(!ce(i)){if(ht(i)){i.items.length>1&&t("Each pair must have its own sequence indicator");let r=i.items[0]||new Ce(new W(null));if(i.commentBefore&&(r.key.commentBefore=r.key.commentBefore?`${i.commentBefore}
${r.key.commentBefore}`:i.commentBefore),i.comment){let s=r.value??r.key;s.comment=s.comment?`${i.comment}
${s.comment}`:i.comment}i=r}n.items[e]=ce(i)?i:new Ce(i)}}else t("Expected a sequence for this tag");return n}function Eu(n,t,e){let{replacer:i}=e,r=new Xe(n);r.tag="tag:yaml.org,2002:pairs";let s=0;if(t&&Symbol.iterator in Object(t))for(let a of t){typeof i=="function"&&(a=i.call(t,String(s++),a));let o,l;if(Array.isArray(a))if(a.length===2)o=a[0],l=a[1];else throw new TypeError(`Expected [key, value] tuple: ${a}`);else if(a&&a instanceof Object){let c=Object.keys(a);if(c.length===1)o=c[0],l=a[o];else throw new TypeError(`Expected tuple with one key, not ${c.length} keys`)}else o=a;r.items.push(rs(o,l,e))}return r}var Qa={collection:"seq",default:!1,tag:"tag:yaml.org,2002:pairs",resolve:Su,createNode:Eu};var ss=class n extends Xe{constructor(){super(),this.add=Me.prototype.add.bind(this),this.delete=Me.prototype.delete.bind(this),this.get=Me.prototype.get.bind(this),this.has=Me.prototype.has.bind(this),this.set=Me.prototype.set.bind(this),this.tag=n.tag}toJSON(t,e){if(!e)return super.toJSON(t);let i=new Map;e?.onCreate&&e.onCreate(i);for(let r of this.items){let s,a;if(ce(r)?(s=_e(r.key,"",e),a=_e(r.value,s,e)):s=_e(r,"",e),i.has(s))throw new Error("Ordered maps must not include duplicate keys");i.set(s,a)}return i}static from(t,e,i){let r=Eu(t,e,i),s=new this;return s.items=r.items,s}};ss.tag="tag:yaml.org,2002:omap";var Ja={collection:"seq",identify:n=>n instanceof Map,nodeClass:ss,default:!1,tag:"tag:yaml.org,2002:omap",resolve(n,t){let e=Su(n,t),i=[];for(let{key:r}of e.items)ne(r)&&(i.includes(r.value)?t(`Ordered maps must not include duplicate keys: ${r.value}`):i.push(r.value));return Object.assign(new ss,e)},createNode:(n,t,e)=>ss.from(n,t,e)};function ey({value:n,source:t},e){return t&&(n?Tu:Mu).test.test(t)?t:n?e.options.trueStr:e.options.falseStr}var Tu={identify:n=>n===!0,default:!0,tag:"tag:yaml.org,2002:bool",test:/^(?:Y|y|[Yy]es|YES|[Tt]rue|TRUE|[Oo]n|ON)$/,resolve:()=>new W(!0),stringify:ey},Mu={identify:n=>n===!1,default:!0,tag:"tag:yaml.org,2002:bool",test:/^(?:N|n|[Nn]o|NO|[Ff]alse|FALSE|[Oo]ff|OFF)$/,resolve:()=>new W(!1),stringify:ey};var ty={identify:n=>typeof n=="number",default:!0,tag:"tag:yaml.org,2002:float",test:/^(?:[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN)$/,resolve:n=>n.slice(-3).toLowerCase()==="nan"?NaN:n[0]==="-"?Number.NEGATIVE_INFINITY:Number.POSITIVE_INFINITY,stringify:et},ny={identify:n=>typeof n=="number",default:!0,tag:"tag:yaml.org,2002:float",format:"EXP",test:/^[-+]?(?:[0-9][0-9_]*)?(?:\.[0-9_]*)?[eE][-+]?[0-9]+$/,resolve:n=>parseFloat(n.replace(/_/g,"")),stringify(n){let t=Number(n.value);return isFinite(t)?t.toExponential():et(n)}},iy={identify:n=>typeof n=="number",default:!0,tag:"tag:yaml.org,2002:float",test:/^[-+]?(?:[0-9][0-9_]*)?\.[0-9_]*$/,resolve(n){let t=new W(parseFloat(n.replace(/_/g,""))),e=n.indexOf(".");if(e!==-1){let i=n.substring(e+1).replace(/_/g,"");i[i.length-1]==="0"&&(t.minFractionDigits=i.length)}return t},stringify:et};var Za=n=>typeof n=="bigint"||Number.isInteger(n);function jl(n,t,e,{intAsBigInt:i}){let r=n[0];if((r==="-"||r==="+")&&(t+=1),n=n.substring(t).replace(/_/g,""),i){switch(e){case 2:n=`0b${n}`;break;case 8:n=`0o${n}`;break;case 16:n=`0x${n}`;break}let a=BigInt(n);return r==="-"?BigInt(-1)*a:a}let s=parseInt(n,e);return r==="-"?-1*s:s}function Ou(n,t,e){let{value:i}=n;if(Za(i)){let r=i.toString(t);return i<0?"-"+e+r.substr(1):e+r}return et(n)}var ry={identify:Za,default:!0,tag:"tag:yaml.org,2002:int",format:"BIN",test:/^[-+]?0b[0-1_]+$/,resolve:(n,t,e)=>jl(n,2,2,e),stringify:n=>Ou(n,2,"0b")},sy={identify:Za,default:!0,tag:"tag:yaml.org,2002:int",format:"OCT",test:/^[-+]?0[0-7_]+$/,resolve:(n,t,e)=>jl(n,1,8,e),stringify:n=>Ou(n,8,"0")},ay={identify:Za,default:!0,tag:"tag:yaml.org,2002:int",test:/^[-+]?[0-9][0-9_]*$/,resolve:(n,t,e)=>jl(n,0,10,e),stringify:et},oy={identify:Za,default:!0,tag:"tag:yaml.org,2002:int",format:"HEX",test:/^[-+]?0x[0-9a-fA-F_]+$/,resolve:(n,t,e)=>jl(n,2,16,e),stringify:n=>Ou(n,16,"0x")};var as=class n extends Me{constructor(t){super(t),this.tag=n.tag}add(t){let e;ce(t)?e=t:t&&typeof t=="object"&&"key"in t&&"value"in t&&t.value===null?e=new Ce(t.key,null):e=new Ce(t,null),Ai(this.items,e.key)||this.items.push(e)}get(t,e){let i=Ai(this.items,t);return!e&&ce(i)?ne(i.key)?i.key.value:i.key:i}set(t,e){if(typeof e!="boolean")throw new Error(`Expected boolean value for set(key, value) in a YAML set, not ${typeof e}`);let i=Ai(this.items,t);i&&!e?this.items.splice(this.items.indexOf(i),1):!i&&e&&this.items.push(new Ce(t))}toJSON(t,e){return super.toJSON(t,e,Set)}toString(t,e,i){if(!t)return JSON.stringify(this);if(this.hasAllNullValues(!0))return super.toString(Object.assign({},t,{allNullValues:!0}),e,i);throw new Error("Set items must all have null values")}static from(t,e,i){let{replacer:r}=i,s=new this(t);if(e&&Symbol.iterator in Object(e))for(let a of e)typeof r=="function"&&(a=r.call(e,a,a)),s.items.push(rs(a,null,i));return s}};as.tag="tag:yaml.org,2002:set";var Xa={collection:"map",identify:n=>n instanceo Line truncated
`)?(e.push("..."),e.push(Ht(l,""))):e.push(`... ${l}`)}else e.push("...");else{let l=n.comment;l&&a&&(l=l.replace(/^\n+/,"")),l&&((!a||o)&&e[e.length-1]!==""&&e.push(""),e.push(Ht(s(l),"")))}return e.join(`
`)+`
`}var yn=class n{constructor(t,e,i){this.commentBefore=null,this.comment=null,this.errors=[],this.warnings=[],Object.defineProperty(this,ct,{value:kl});let r=null;typeof e=="function"||Array.isArray(e)?r=e:i===void 0&&e&&(i=e,e=void 0);let s=Object.assign({intAsBigInt:!1,keepSourceTokens:!1,logLevel:"warn",prettyErrors:!0,strict:!0,stringKeys:!1,uniqueKeys:!0,version:"1.2"},i);this.options=s;let{version:a}=s;i?._directives?(this.directives=i._directives.atDocument(),this.directives.yaml.explicit&&(a=this.directives.yaml.version)):this.directives=new In({version:a}),this.setSchema(a,i),this.contents=t===void 0?null:this.createNode(t,r,i)}clone(){let t=Object.create(n.prototype,{[ct]:{value:kl}});return t.commentBefore=this.commentBefore,t.comment=this.comment,t.errors=this.errors.slice(),t.warnings=this.warnings.slice(),t.options=Object.assign({},this.options),this.directives&&(t.directives=this.directives.clone()),t.schema=this.schema.clone(),t.contents=ue(this.contents)?this.contents.clone(t.schema):this.contents,this.range&&(t.range=this.range.slice()),t}add(t){ls(this.contents)&&this.contents.add(t)}addIn(t,e){ls(this.contents)&&this.contents.addIn(t,e)}createAlias(t,e){if(!t.anchor){let i=yu(this);t.anchor=!e||i.has(e)?bu(e||"a",i):e}return new Gn(t.anchor)}createNode(t,e,i){let r;if(typeof e=="function")t=e.call({"":t},"",t),r=e;else if(Array.isArray(e)){let g=k=>typeof k=="number"||k instanceof String||k instanceof Number,b=e.filter(g).map(String);b.length>0&&(e=e.concat(b)),r=e}else i===void 0&&e&&(i=e,e=void 0);let{aliasDuplicateObjects:s,anchorPrefix:a,flow:o,keepUndefined:l,onTagObj:c,tag:u}=i??{},{onAnchor:d,setAnchors:m,sourceObjects:p}=jg(this,a||"a"),h={aliasDuplicateObjects:s??!0,keepUndefined:l??!1,onAnchor:d,onTagObj:c,replacer:r,schema:this.schema,sourceObjects:p},f=Qn(t,u,h);return o&&pe(f)&&(f.flow=!0),m(),f}createPair(t,e,i={}){let r=this.createNode(t,null,i),s=this.createNode(e,null,i);return new Ce(r,s)}delete(t){return ls(this.contents)?this.contents.delete(t):!1}deleteIn(t){return ns(t)?this.contents==null?!1:(this.contents=null,!0):ls(this.contents)?this.contents.deleteIn(t):!1}get(t,e){return pe(this.contents)?this.contents.get(t,e):void 0}getIn(t,e){return ns(t)?!e&&ne(this.contents)?this.contents.value:this.contents:pe(this.contents)?this.contents.getIn(t,e):void 0}has(t){return pe(this.contents)?this.contents.has(t):!1}hasIn(t){return ns(t)?this.contents!==void 0:pe(this.contents)?this.contents.hasIn(t):!1}set(t,e){this.contents==null?this.contents=ja(this.schema,[t],e):ls(this.contents)&&this.contents.set(t,e)}setIn(t,e){ns(t)?this.contents=e:this.contents==null?this.contents=ja(this.schema,Array.from(t),e):ls(this.contents)&&this.contents.setIn(t,e)}setSchema(t,e={}){typeof t=="number"&&(t=String(t));let i;switch(t){case"1.1":this.directives?this.directives.yaml.version="1.1":this.directives=new In({version:"1.1"}),i={resolveKnownTags:!1,schema:"yaml-1.1"};break;case"1.2":case"next":this.directives?this.directives.yaml.version=t:this.directives=new In({version:t}),i={resolveKnownTags:!0,schema:"core"};break;case null:this.directives&&delete this.directives,i=null;break;default:{let r=JSON.stringify(t);throw new Error(`Expected '1.1', '1.2' or null as first argument, but found: ${r}`)}}if(e.schema instanceof Object)this.schema=e.schema;else if(i)this.schema=new eo(Object.assign(i,e));else throw new Error("With a null YAML version, the { schema: Schema } option is required")}toJS({json:t,jsonArg:e,mapAsMap:i,maxAliasCount:r,onAnchor:s,reviver:a}={}){let o={anchors:new Map,doc:this,keep:!t,mapAsMap:i===!0,mapKeyWarned:!1,maxAliasCount:typeof r=="number"?r:100},l=_e(this.contents,e??"",o);if(typeof s=="function")for(let{count:c,res:u}of o.anchors.values())s(u,c);return typeof a=="function"?ki(a,{"":l},"",l):l}toJSON(t,e){return this.toJS({json:!0,jsonArg:t,mapAsMap:!1,onAnchor:e})}toString(t={}){if(this.errors.length>0)throw new Error("Document with errors cannot be stringified");if("indent"in t&&(!Number.isInteger(t.indent)||Number(t.indent)<=0)){let e=JSON.stringify(t.indent);throw new Error(`"indent" option must be a positive integer, not ${e}`)}return my(this,t)}};function ls(n){if(pe(n))return!0;throw new Error("Expected a YAML collection as document contents")}var to=class extends Error{constructor(t,e,i,r){super(),this.name=t,this.code=i,this.message=r,this.pos=e}},tt=class extends to{constructor(t,e,i){super("YAMLParseError",t,e,i)}},no=class extends to{constructor(t,e,i){super("YAMLWarning",t,e,i)}},Ru=(n,t)=>e=>{if(e.pos[0]===-1)return;e.linePos=e.pos.map(o=>t.linePos(o));let{line:i,col:r}=e.linePos[0];e.message+=` at line ${i}, column ${r}`;let s=r-1,a=n.substring(t.lineStarts[i-1],t.lineStarts[i]).replace(/[\n\r]+$/,"");if(s>=60&&a.length>80){let o=Math.min(s-39,a.length-79);a="\u2026"+a.substring(o),s-=o-1}if(a.length>80&&(a=a.substring(0,79)+"\u2026"),i>1&&/^ *$/.test(a.substring(0,s))){let o=n.substring(t.lineStarts[i-2],t.lineStarts[i-1]);o.length>80&&(o=o.substr Line truncated
`),a=o+a}if(/[^ ]/.test(a)){let o=1,l=e.linePos[1];l?.line===i&&l.col>r&&(o=Math.max(1,Math.min(l.col-r,80-s)));let c=" ".repeat(s)+"^".repeat(o);e.message+=`:
${a}
${c}
`}};function Nn(n,{flow:t,indicator:e,next:i,offset:r,onError:s,parentIndent:a,startOnNewline:o}){let l=!1,c=o,u=o,d="",m="",p=!1,h=!1,f=null,g=null,b=null,k=null,x=null,E=null,C=null;for(let F of n)switch(h&&(F.type!=="space"&&F.type!=="newline"&&F.type!=="comma"&&s(F.offset,"MISSING_CHAR","Tags and anchors must be separated from the next token by white space"),h=!1),f&&(c&&F.type!=="comment"&&F.type!=="newline"&&s(f,"TAB_AS_INDENT","Tabs are not allowed as indentation"),f=null),F.type){case"space":!t&&(e!=="doc-start"||i?.type!=="flow-collection")&&F.source.includes(" ")&&(f=F),u=!0;break;case"comment":{u||s(F,"MISSING_CHAR","Comments must be separated from other tokens by white space characters");let P=F.source.substring(1)||" ";d?d+=m+P:d=P,m="",c=!1;break}case"newline":c?d?d+=F.source:(!E||e!=="seq-item-ind")&&(l=!0):m+=F.source,c=!0,p=!0,(g||b)&&(k=F),u=!0;break;case"anchor":g&&s(F,"MULTIPLE_ANCHORS","A node can have at most one anchor"),F.source.endsWith(":")&&s(F.offset+F.source.length-1,"BAD_ALIAS","Anchor ending in : is ambiguous",!0),g=F,C??(C=F.offset),c=!1,u=!1,h=!0;break;case"tag":{b&&s(F,"MULTIPLE_TAGS","A node can have at most one tag"),b=F,C??(C=F.offset),c=!1,u=!1,h=!0;break}case e:(g||b)&&s(F,"BAD_PROP_ORDER",`Anchors and tags must be after the ${F.source} indicator`),E&&s(F,"UNEXPECTED_TOKEN",`Unexpected ${F.source} in ${t??"collection"}`),E=F,c=e==="seq-item-ind"||e==="explicit-key-ind",u=!1;break;case"comma":if(t){x&&s(F,"UNEXPECTED_TOKEN",`Unexpected , in ${t}`),x=F,c=!1,u=!1;break}default:s(F,"UNEXPECTED_TOKEN",`Unexpected ${F.type} token`),c=!1,u=!1}let M=n[n.length-1],N=M?M.offset+M.source.length:r;return h&&i&&i.type!=="space"&&i.type!=="newline"&&i.type!=="comma"&&(i.type!=="scalar"||i.source!=="")&&s(i.offset,"MISSING_CHAR","Tags and anchors must be separated from the next token by white space"),f&&(c&&f.indent<=a||i?.type==="block-map"||i?.type==="block-seq")&&s(f,"TAB_AS_INDENT","Tabs are not allowed as indentation"),{comma:x,found:E,spaceBefore:l,comment:d,hasNewline:p,anchor:g,tag:b,newlineAfterProp:k,end:N,start:C??N}}function xi(n){if(!n)return null;switch(n.type){case"alias":case"scalar":case"double-quoted-scalar":case"single-quoted-scalar":if(n.source.includes(`
`))return!0;if(n.end){for(let t of n.end)if(t.type==="newline")return!0}return!1;case"flow-collection":for(let t of n.items){for(let e of t.start)if(e.type==="newline")return!0;if(t.sep){for(let e of t.sep)if(e.type==="newline")return!0}if(xi(t.key)||xi(t.value))return!0}return!1;default:return!0}}function io(n,t,e){if(t?.type==="flow-collection"){let i=t.end[0];i.indent===n&&(i.source==="]"||i.source==="}")&&xi(t)&&e(i,"BAD_INDENT","Flow end indicator should be more indented than parent",!0)}}function Vl(n,t,e){let{uniqueKeys:i}=n.options;if(i===!1)return!1;let r=typeof i=="function"?i:(s,a)=>s===a||ne(s)&&ne(a)&&s.value===a.value;return t.some(s=>r(s.key,e))}var py="All mapping items must start at the same column";function fy({composeNode:n,composeEmptyNode:t},e,i,r,s){let a=s?.nodeClass??Me,o=new a(e.schema);e.atRoot&&(e.atRoot=!1);let l=i.offset,c=null;for(let u of i.items){let{start:d,key:m,sep:p,value:h}=u,f=Nn(d,{indicator:"explicit-key-ind",next:m??p?.[0],offset:l,onError:r,parentIndent:i.indent,startOnNewline:!0}),g=!f.found;if(g){if(m&&(m.type==="block-seq"?r(l,"BLOCK_AS_IMPLICIT_KEY","A block sequence may not be used as an implicit map key"):"indent"in m&&m.indent!==i.indent&&r(l,"BAD_INDENT",py)),!f.anchor&&!f.tag&&!p){c=f.end,f.comment&&(o.comment?o.comment+=`
`+f.comment:o.comment=f.comment);continue}(f.newlineAfterProp||xi(m))&&r(m??d[d.length-1],"MULTILINE_IMPLICIT_KEY","Implicit keys need to be on a single line")}else f.found?.indent!==i.indent&&r(l,"BAD_INDENT",py);e.atKey=!0;let b=f.end,k=m?n(e,m,f,r):t(e,b,d,null,f,r);e.schema.compat&&io(i.indent,m,r),e.atKey=!1,Vl(e,o.items,k)&&r(b,"DUPLICATE_KEY","Map keys must be unique");let x=Nn(p??[],{indicator:"map-value-ind",next:h,offset:k.range[2],onError:r,parentIndent:i.indent,startOnNewline:!m||m.type==="block-scalar"});if(l=x.end,x.found){g&&(h?.type==="block-map"&&!x.hasNewline&&r(l,"BLOCK_AS_IMPLICIT_KEY","Nested mappings are not allowed in compact mappings"),e.options.strict&&f.start<x.found.offset-1024&&r(k.range,"KEY_OVER_1024_CHARS","The : indicator must be at most 1024 chars after the start of an implicit block mapping key"));let E=h?n(e,h,x,r):t(e,l,p,null,x,r);e.schema.compat&&io(i.indent,h,r),l=E.range[2];let C=new Ce(k,E);e.options.keepSourceTokens&&(C.srcToken=u),o.items.push(C)}else{g&&r(k.range,"MISSING_CHAR","Implicit map keys need to be followed by map values"),x.comment&&(k.comment?k.comment+=`
`+x.comment:k.comment=x.comment);let E=new Ce(k);e.options.keepSourceTokens&&(E.srcToken=u),o.items.push(E)}}return c&&c<l&&r(c,"IMPOSSIBLE","Map comment with trailing content"),o.range=[i.offset,l,c??l],o}function hy({composeNode:n,composeEmptyNode:t},e,i,r,s){let a=s?.nodeClass??Xe,o=new a(e.schema);e.atRoot&&(e.atRoot=!1),e.atKey&&(e.atKey=!1);let l=i.offset,c=null;for(let{start:u,value:d}of i.items){let m=Nn(u,{indicator:"seq-item-ind",next:d,offset:l,onError:r,parentIndent:i.indent,startOnNewline:!0});if(!m.found)if(m.anchor||m.tag||d)d?.type==="block-seq"?r(m.end,"BAD_INDENT","All sequence items must start at the same column"):r(l,"MISSING_CHAR","Sequence item without - indicator");else{c=m.end,m.comment&&(o.comment=m.comment);continue}let p=d?n(e,d,m,r):t(e,m.end,u,null,m,r);e.schema.compat&&io(i.indent,d,r),l=p.range[2],o.items.push(p)}return o.range=[i.offset,l,c??l],o}function Fn(n,t,e,i){let r="";if(n){let s=!1,a="";for(let o of n){let{source:l,type:c}=o;switch(c){case"space":s=!0;break;case"comment":{e&&!s&&i(o,"MISSING_CHAR","Comments must be separated from other tokens by white space characters");let u=l.substring(1)||" ";r?r+=a+u:r=u,a="";break}case"newline":r&&(a+=l),s=!0;break;default:i(o,"UNEXPECTED_TOKEN",`Unexpected ${c} at node end`)}t+=l.length}}return{comment:r,offset:t}}var Nu="Block collections are not allowed within flow collections",Fu=n=>n&&(n.type==="block-map"||n.type==="block-seq");function gy({composeNode:n,composeEmptyNode:t},e,i,r,s){let a=i.start.source==="{",o=a?"flow map":"flow sequence",l=s?.nodeClass??(a?Me:Xe),c=new l(e.schema);c.flow=!0;let u=e.atRoot;u&&(e.atRoot=!1),e.atKey&&(e.atKey=!1);let d=i.offset+i.start.source.length;for(let g=0;g<i.items.length;++g){let b=i.items[g],{start:k,key:x,sep:E,value:C}=b,M=Nn(k,{flow:o,indicator:"explicit-key-ind",next:x??E?.[0],offset:d,onError:r,parentIndent:i.indent,startOnNewline:!1});if(!M.found){if(!M.anchor&&!M.tag&&!E&&!C){g===0&&M.comma?r(M.comma,"UNEXPECTED_TOKEN",`Unexpected , in ${o}`):g<i.items.length-1&&r(M.start,"UNEXPECTED_TOKEN",`Unexpected empty item in ${o}`),M.comment&&(c.comment?c.comment+=`
`+M.comment:c.comment=M.comment),d=M.end;continue}!a&&e.options.strict&&xi(x)&&r(x,"MULTILINE_IMPLICIT_KEY","Implicit keys of flow sequence pairs need to be on a single line")}if(g===0)M.comma&&r(M.comma,"UNEXPECTED_TOKEN",`Unexpected , in ${o}`);else if(M.comma||r(M.start,"MISSING_CHAR",`Missing , between ${o} items`),M.comment){let N="";e:for(let F of k)switch(F.type){case"comma":case"space":break;case"comment":N=F.source.substring(1);break e;default:break e}if(N){let F=c.items[c.items.length-1];ce(F)&&(F=F.value??F.key),F.comment?F.comment+=`
`+N:F.comment=N,M.comment=M.comment.substring(N.length+1)}}if(!a&&!E&&!M.found){let N=C?n(e,C,M,r):t(e,M.end,E,null,M,r);c.items.push(N),d=N.range[2],Fu(C)&&r(N.range,"BLOCK_IN_FLOW",Nu)}else{e.atKey=!0;let N=M.end,F=x?n(e,x,M,r):t(e,N,k,null,M,r);Fu(x)&&r(F.range,"BLOCK_IN_FLOW",Nu),e.atKey=!1;let P=Nn(E??[],{flow:o,indicator:"map-value-ind",next:C,offset:F.range[2],onError:r,parentIndent:i.indent,startOnNewline:!1});if(P.found){if(!a&&!M.found&&e.options.strict){if(E)for(let j of E){if(j===P.found)break;if(j.type==="newline"){r(j,"MULTILINE_IMPLICIT_KEY","Implicit keys of flow sequence pairs need to be on a single line");break}}M.start<P.found.offset-1024&&r(P.found,"KEY_OVER_1024_CHARS","The : indicator must be at most 1024 chars after the start of an implicit flow sequence key")}}else C&&("source"in C&&C.source?.[0]===":"?r(C,"MISSING_CHAR",`Missing space after : in ${o}`):r(P.start,"MISSING_CHAR",`Missing , or : between ${o} items`));let q=C?n(e,C,P,r):P.found?t(e,P.end,E,null,P,r):null;q?Fu(C)&&r(q.range,"BLOCK_IN_FLOW",Nu):P.comment&&(F.comment?F.comment+=`
`+P.comment:F.comment=P.comment);let $=new Ce(F,q);if(e.options.keepSourceTokens&&($.srcToken=b),a){let j=c;Vl(e,j.items,F)&&r(N,"DUPLICATE_KEY","Map keys must be unique"),j.items.push($)}else{let j=new Me(e.schema);j.flow=!0,j.items.push($);let U=(q??F).range;j.range=[F.range[0],U[1],U[2]],c.items.push(j)}d=q?q.range[2]:P.end}}let m=a?"}":"]",[p,...h]=i.end,f=d;if(p?.source===m)f=p.offset+p.source.length;else{let g=o[0].toUpperCase()+o.substring(1),b=u?`${g} must end with a ${m}`:`${g} in block collection must be sufficiently indented and end with a ${m}`;r(d,u?"MISSING_CHAR":"BAD_INDENT",b),p&&p.source.length!==1&&h.unshift(p)}if(h.length>0){let g=Fn(h,f,e.options.strict,r);g.comment&&(c.comment?c.comment+=`
`+g.comment:c.comment=g.comment),c.range=[i.offset,f,g.offset]}else c.range=[i.offset,f,f];return c}function Bu(n,t,e,i,r,s){let a=e.type==="block-map"?fy(n,t,e,i,s):e.type==="block-seq"?hy(n,t,e,i,s):gy(n,t,e,i,s),o=a.constructor;return r==="!"||r===o.tagName?(a.tag=o.tagName,a):(r&&(a.tag=r),a)}function yy(n,t,e,i,r){let s=i.tag,a=s?t.directives.tagName(s.source,m=>r(s,"TAG_RESOLVE_FAILED",m)):null;if(e.type==="block-seq"){let{anchor:m,newlineAfterProp:p}=i,h=m&&s?m.offset>s.offset?m:s:m??s;h&&(!p||p.offset<h.offset)&&r(h,"MISSING_CHAR","Missing newline after block sequence props")}let o=e.type==="block-map"?"map":e.type==="block-seq"?"seq":e.start.source==="{"?"map":"seq";if(!s||!a||a==="!"||a===Me.tagName&&o==="map"||a===Xe.tagName&&o==="seq")return Bu(n,t,e,r,a);let l=t.schema.tags.find(m=>m.tag===a&&m.collection===o);if(!l){let m=t.schema.knownTags[a];if(m?.collection===o)t.schema.tags.push(Object.assign({},m,{default:!1})),l=m;else return m?r(s,"BAD_COLLECTION_TYPE",`${m.tag} used for ${o} collection, but expects ${m.collection??"scalar"}`,!0):r(s,"TAG_RESOLVE_FAILED",`Unresolved tag: ${a}`,!0),Bu(n,t,e,r,a)}let c=Bu(n,t,e,r,a,l),u=l.resolve?.(c,m=>r(s,"TAG_RESOLVE_FAILED",m),t.options)??c,d=ue(u)?u:new W(u);return d.range=c.range,d.tag=a,l?.format&&(d.format=l.format),d}function Gl(n,t,e){let i=t.offset,r=bL(t,n.options.strict,e);if(!r)return{value:"",type:null,comment:"",range:[i,i,i]};let s=r.mode===">"?W.BLOCK_FOLDED:W.BLOCK_LITERAL,a=t.source?kL(t.source):[],o=a.length;for(let f=a.length-1;f>=0;--f){let g=a[f][1];if(g===""||g==="\r")o=f;else break}if(o===0){let f=r.chomp==="+"&&a.length>0?`
`.repeat(Math.max(1,a.length-1)):"",g=i+r.length;return t.source&&(g+=t.source.length),{value:f,type:s,comment:r.comment,range:[i,g,g]}}let l=t.indent+r.indent,c=t.offset+r.length,u=0;for(let f=0;f<o;++f){let[g,b]=a[f];if(b===""||b==="\r")r.indent===0&&g.length>l&&(l=g.length);else{g.length<l&&e(c+g.length,"MISSING_CHAR","Block scalars with more-indented leading empty lines must use an explicit indentation indicator"),r.indent===0&&(l=g.length),u=f,l===0&&!n.atRoot&&e(c,"BAD_INDENT","Block scalar values in collections must be indented");break}c+=g.length+b.length+1}for(let f=a.length-1;f>=o;--f)a[f][0].length>l&&(o=f+1);let d="",m="",p=!1;for(let f=0;f<u;++f)d+=a[f][0].slice(l)+`
`;for(let f=u;f<o;++f){let[g,b]=a[f];c+=g.length+b.length+1;let k=b[b.length-1]==="\r";if(k&&(b=b.slice(0,-1)),b&&g.length<l){let E=`Block scalar lines must not be less indented than their ${r.indent?"explicit indentation indicator":"first line"}`;e(c-b.length-(k?2:1),"BAD_INDENT",E),g=""}s===W.BLOCK_LITERAL?(d+=m+g.slice(l)+b,m=`
`):g.length>l||b[0]===" "?(m===" "?m=`
`:!p&&m===`
`&&(m=`
`),d+=m+g.slice(l)+b,m=`
`,p=!0):b===""?m===`
`?d+=`
`:m=`
`:(d+=m+b,m=" ",p=!1)}switch(r.chomp){case"-":break;case"+":for(let f=o;f<a.length;++f)d+=`
`+a[f][0].slice(l);d[d.length-1]!==`
`&&(d+=`
`);break;default:d+=`
`}let h=i+r.length+t.source.length;return{value:d,type:s,comment:r.comment,range:[i,h,h]}}function bL({offset:n,props:t},e,i){if(t[0].type!=="block-scalar-header")return i(t[0],"IMPOSSIBLE","Block scalar header not found"),null;let{source:r}=t[0],s=r[0],a=0,o="",l=-1;for(let m=1;m<r.length;++m){let p=r[m];if(!o&&(p==="-"||p==="+"))o=p;else{let h=Number(p);!a&&h?a=h:l===-1&&(l=n+m)}}l!==-1&&i(l,"UNEXPECTED_TOKEN",`Block scalar header includes extra characters: ${r}`);let c=!1,u="",d=r.length;for(let m=1;m<t.length;++m){let p=t[m];switch(p.type){case"space":c=!0;case"newline":d+=p.source.length;break;case"comment":e&&!c&&i(p,"MISSING_CHAR","Comments must be separated from other tokens by white space characters"),d+=p.source.length,u=p.source.substring(1);break;case"error":i(p,"UNEXPECTED_TOKEN",p.message),d+=p.source.length;break;default:{let h=`Unexpected token in block scalar header: ${p.type}`;i(p,"UNEXPECTED_TOKEN",h);let f=p.source;f&&typeof f=="string"&&(d+=f.length)}}}return{mode:s,indent:a,chomp:o,comment:u,length:d}}function kL(n){let t=n.split(/\n( *)/),e=t[0],i=e.match(/^( *)/),s=[i?.[1]?[i[1],e.slice(i[1].length)]:["",e]];for(let a=1;a<t.length;a+=2)s.push([t[a],t[a+1]]);return s}function Ql(n,t,e){let{offset:i,type:r,source:s,end:a}=n,o,l,c=(m,p,h)=>e(i+m,p,h);switch(r){case"scalar":o=W.PLAIN,l=vL(s,c);break;case"single-quoted-scalar":o=W.QUOTE_SINGLE,l=AL(s,c);break;case"double-quoted-scalar":o=W.QUOTE_DOUBLE,l=wL(s,c);break;default:return e(n,"UNEXPECTED_TOKEN",`Expected a flow scalar value, but found: ${r}`),{value:"",type:null,comment:"",range:[i,i+s.length,i+s.length]}}let u=i+s.length,d=Fn(a,u,t,e);return{value:l,type:o,comment:d.comment,range:[i,u,d.offset]}}function vL(n,t){let e="";switch(n[0]){case" ":e="a tab character";break;case",":e="flow indicator character ,";break;case"%":e="directive indicator character %";break;case"|":case">":{e=`block scalar indicator ${n[0]}`;break}case"@":case"`":{e=`reserved character ${n[0]}`;break}}return e&&t(0,"BAD_SCALAR_START",`Plain value cannot start with ${e}`),by(n)}function AL(n,t){return(n[n.length-1]!=="'"||n.length===1)&&t(n.length,"MISSING_CHAR","Missing closing 'quote"),by(n.slice(1,-1)).replace(/''/g,"'")}function by(n){let t=/(.*?)\r?\n/sy,e=t.exec(n);if(!e)return n;let i,r;try{i=new RegExp("(?<![ ])[ ]+$"),r=new RegExp("^[ ]+|(?<![ ])[ ]+$","g")}catch{i=/[ \t]+$/,r=/^[ \t]+|[ \t]+$/g}let s=e[1].replace(i,""),a=" ",o=t.lastIndex;for(;e=t.exec(n);){let c=e[1].replace(r,"");c===""?a===`
`?s+=a:a=`
`:(s+=a+c,a=" "),o=t.lastIndex}let l=/[ \t]*(.*)/sy;return l.lastIndex=o,e=l.exec(n),s+a+(e?.[1]??"")}function wL(n,t){let e="";for(let i=1;i<n.length-1;++i){let r=n[i];if(!(r==="\r"&&n[i+1]===`
`))if(r===`
`){let{fold:s,offset:a}=xL(n,i);e+=s,i=a}else if(r==="\\"){let s=n[++i],a=LL[s];if(a)e+=a;else if(s===`
`)for(s=n[i+1];s===" "||s===" ";)s=n[++i+1];else if(s==="\r"&&n[i+1]===`
`)for(s=n[++i+1];s===" "||s===" ";)s=n[++i+1];else if(s==="x"||s==="u"||s==="U"){let o=s==="x"?2:s==="u"?4:8;e+=SL(n,i+1,o,t),i+=o}else{let o=n.substr(i-1,2);t(i-1,"BAD_DQ_ESCAPE",`Invalid escape sequence ${o}`),e+=o}}else if(r===" "||r===" "){let s=i,a=n[i+1];for(;a===" "||a===" ";)a=n[++i+1];a!==`
`&&!(a==="\r"&&n[i+2]===`
`)&&(e+=i>s?n.slice(s,i+1):r)}else e+=r}return(n[n.length-1]!=='"'||n.length===1)&&t(n.length,"MISSING_CHAR",'Missing closing "quote'),e}function xL(n,t){let e="",i=n[t+1];for(;(i===" "||i===" "||i===`
`||i==="\r")&&!(i==="\r"&&n[t+2]!==`
`);)i===`
`&&(e+=`
`),t+=1,i=n[t+1];return e||(e=" "),{fold:e,offset:t}}var LL={0:"\0",a:"\x07",b:"\b",e:"\x1B",f:"\f",n:`
`,r:"\r",t:" ",v:"\v",N:"\x85",_:"\xA0",L:"\u2028",P:"\u2029"," ":" ",'"':'"',"/":"/","\\":"\\"," ":" "};function SL(n,t,e,i){let r=n.substr(t,e),a=r.length===e&&/^[0-9a-fA-F]+$/.test(r)?parseInt(r,16):NaN;try{return String.fromCodePoint(a)}catch{let o=n.substr(t-2,e+2);return i(t-2,"BAD_DQ_ESCAPE",`Invalid escape sequence ${o}`),o}}function Du(n,t,e,i){let{value:r,type:s,comment:a,range:o}=t.type==="block-scalar"?Gl(n,t,i):Ql(t,n.options.strict,i),l=e?n.directives.tagName(e.source,d=>i(e,"TAG_RESOLVE_FAILED",d)):null,c;n.options.stringKeys&&n.atKey?c=n.schema[Ot]:l?c=EL(n.schema,r,l,e,i):t.type==="scalar"?c=TL(n,r,t,i):c=n.schema[Ot];let u;try{let d=c.resolve(r,m=>i(e??t,"TAG_RESOLVE_FAILED",m),n.options);u=ne(d)?d:new W(d)}catch(d){let m=d instanceof Error?d.message:String(d);i(e??t,"TAG_RESOLVE_FAILED",m),u=new W(r)}return u.range=o,u.source=r,s&&(u.type=s),l&&(u.tag=l),c.format&&(u.format=c.format),a&&(u.comment=a),u}function EL(n,t,e,i,r){if(e==="!")return n[Ot];let s=[];for(let o of n.tags)if(!o.collection&&o.tag===e)if(o.default&&o.test)s.push(o);else return o;for(let o of s)if(o.test?.test(t))return o;let a=n.knownTags[e];return a&&!a.collection?(n.tags.push(Object.assign({},a,{default:!1,test:void 0})),a):(r(i,"TAG_RESOLVE_FAILED",`Unresolved tag: ${e}`,e!=="tag:yaml.org,2002:str"),n[Ot])}function TL({atKey:n,directives:t,schema:e},i,r,s){let a=e.tags.find(o=>(o.default===!0||n&&o.default==="key")&&o.test?.test(i))||e[Ot];if(e.compat){let o=e.compat.find(l=>l.default&&l.test?.test(i))??e[Ot];if(a.tag!==o.tag){let l=t.tagString(a.tag),c=t.tagString(o.tag),u=`Value may be parsed as either ${l} or ${c}`;s(r,"TAG_RESOLVE_FAILED",u,!0)}}return a}function ky(n,t,e){if(t){e??(e=t.length);for(let i=e-1;i>=0;--i){let r=t[i];switch(r.type){case"space":case"comment":case"newline":n-=r.source.length;continue}for(r=t[++i];r?.type==="space";)n+=r.source.length,r=t[++i];break}}return n}var ML={composeNode:Yu,composeEmptyNode:Jl};function Yu(n,t,e,i){let r=n.atKey,{spaceBefore:s,comment:a,anchor:o,tag:l}=e,c,u=!0;switch(t.type){case"alias":c=OL(n,t,i),(o||l)&&i(t,"ALIAS_PROPS","An alias node must not specify any properties");break;case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":case"block-scalar":c=Du(n,t,l,i),o&&(c.anchor=o.source.substring(1));break;case"block-map":case"block-seq":case"flow-collection":try{c=yy(ML,n,t,e,i),o&&(c.anchor=o.source.substring(1))}catch(d){let m=d instanceof Error?d.message:String(d);i(t,"RESOURCE_EXHAUSTION",m)}break;default:{let d=t.type==="error"?t.message:`Unsupported token (type: ${t.type})`;i(t,"UNEXPECTED_TOKEN",d),u=!1}}return c??(c=Jl(n,t.offset,void 0,null,e,i)),o&&c.anchor===""&&i(o,"BAD_ALIAS","Anchor cannot be an empty string"),r&&n.options.stringKeys&&(!ne(c)||typeof c.value!="string"||c.tag&&c.tag!=="tag:yaml.org,2002:str")&&i(l??t,"NON_STRING_KEY","With stringKeys, all keys must be strings"),s&&(c.spaceBefore=!0),a&&(t.type==="scalar"&&t.source===""?c.comment=a:c.commentBefore=a),n.options.keepSourceTokens&&u&&(c.srcToken=t),c}function Jl(n,t,e,i,{spaceBefore:r,comment:s,anchor:a,tag:o,end:l},c){let u={type:"scalar",offset:ky(t,e,i),indent:-1,source:""},d=Du(n,u,o,c);return a&&(d.anchor=a.source.substring(1),d.anchor===""&&c(a,"BAD_ALIAS","Anchor cannot be an empty string")),r&&(d.spaceBefore=!0),s&&(d.comment=s,d.range[2]=l),d}function OL({options:n},{offset:t,source:e,end:i},r){let s=new Gn(e.substring(1));s.source===""&&r(t,"BAD_ALIAS","Alias cannot be an empty string"),s.source.endsWith(":")&&r(t+e.length-1,"BAD_ALIAS","Alias ending in : is ambiguous",!0);let a=t+e.length,o=Fn(i,a,n.strict,r);return s.range=[t,a,o.offset],o.comment&&(s.comment=o.comment),s}function vy(n,t,{offset:e,start:i,value:r,end:s},a){let o=Object.assign({_directives:t},n),l=new yn(void 0,o),c={atKey:!1,atRoot:!0,directives:l.directives,options:l.options,schema:l.schema},u=Nn(i,{indicator:"doc-start",next:r??s?.[0],offset:e,onError:a,parentIndent:0,startOnNewline:!0});u.found&&(l.directives.docStart=!0,r&&(r.type==="block-map"||r.type==="block-seq")&&!u.hasNewline&&a(u.end,"MISSING_CHAR","Block collection cannot start on same line with directives-end marker")),l.contents=r?Yu(c,r,u,a):Jl(c,u.end,i,null,u,a);let d=l.contents.range[2],m=Fn(s,d,!1,a);return m.comment&&(l.comment=m.comment),l.range=[e,d,m.offset],l}function ro(n){if(typeof n=="number")return[n,n+1];if(Array.isArray(n))return n.length===2?n:[n[0],n[1]];let{offset:t,source:e}=n;return[t,t+(typeof e=="string"?e.length:1)]}function Ay(n){let t="",e=!1,i=!1;for(let r=0;r<n.length;++r){let s=n[r];switch(s[0]){case"#":t+=(t===""?"":i?`
`:`
`)+(s.substring(1)||" "),e=!0,i=!1;break;case"%":n[r+1]?.[0]!=="#"&&(r+=1),e=!1;break;default:e||(i=!0),e=!1}}return{comment:t,afterEmptyLine:i}}var so=class{constructor(t={}){this.doc=null,this.atDirectives=!1,this.prelude=[],this.errors=[],this.warnings=[],this.onError=(e,i,r,s)=>{let a=ro(e);s?this.warnings.push(new no(a,i,r)):this.errors.push(new tt(a,i,r))},this.directives=new In({version:t.version||"1.2"}),this.options=t}decorate(t,e){let{comment:i,afterEmptyLine:r}=Ay(this.prelude);if(i){let s=t.contents;if(e)t.comment=t.comment?`${t.comment}
${i}`:i;else if(r||t.directives.docStart||!s)t.commentBefore=i;else if(pe(s)&&!s.flow&&s.items.length>0){let a=s.items[0];ce(a)&&(a=a.key);let o=a.commentBefore;a.commentBefore=o?`${i}
${o}`:i}else{let a=s.commentBefore;s.commentBefore=a?`${i}
${a}`:i}}if(e){for(let s=0;s<this.errors.length;++s)t.errors.push(this.errors[s]);for(let s=0;s<this.warnings.length;++s)t.warnings.push(this.warnings[s])}else t.errors=this.errors,t.warnings=this.warnings;this.prelude=[],this.errors=[],this.warnings=[]}streamInfo(){return{comment:Ay(this.prelude).comment,directives:this.directives,errors:this.errors,warnings:this.warnings}}*compose(t,e=!1,i=-1){for(let r of t)yield*this.next(r);yield*this.end(e,i)}*next(t){switch(t.type){case"directive":this.directives.add(t.source,(e,i,r)=>{let s=ro(t);s[0]+=e,this.onError(s,"BAD_DIRECTIVE",i,r)}),this.prelude.push(t.source),this.atDirectives=!0;break;case"document":{let e=vy(this.options,this.directives,t,this.onError);this.atDirectives&&!e.directives.docStart&&this.onError(t,"MISSING_CHAR","Missing directives-end/doc-start indicator line"),this.decorate(e,!1),this.doc&&(yield this.doc),this.doc=e,this.atDirectives=!1;break}case"byte-order-mark":case"space":break;case"comment":case"newline":this.prelude.push(t.source);break;case"error":{let e=t.source?`${t.message}: ${JSON.stringify(t.source)}`:t.message,i=new tt(ro(t),"UNEXPECTED_TOKEN",e);this.atDirectives||!this.doc?this.errors.push(i):this.doc.errors.push(i);break}case"doc-end":{if(!this.doc){let i="Unexpected doc-end without preceding document";this.errors.push(new tt(ro(t),"UNEXPECTED_TOKEN",i));break}this.doc.directives.docEnd=!0;let e=Fn(t.end,t.offset+t.source.length,this.doc.options.strict,this.onError);if(this.decorate(this.doc,!0),e.comment){let i=this.doc.comment;this.doc.comment=i?`${i}
${e.comment}`:e.comment}this.doc.range[2]=e.offset;break}default:this.errors.push(new tt(ro(t),"UNEXPECTED_TOKEN",`Unsupported token ${t.type}`))}}*end(t=!1,e=-1){if(this.doc)this.decorate(this.doc,!0),yield this.doc,this.doc=null;else if(t){let i=Object.assign({_directives:this.directives},this.options),r=new yn(void 0,i);this.atDirectives&&this.onError(e,"MISSING_CHAR","Missing directives-end indicator line"),r.range=[0,e,e],this.decorate(r,!1),yield r}}};var ec={};ud(ec,{BOM:()=>ao,DOCUMENT:()=>oo,FLOW_END:()=>lo,SCALAR:()=>cs,createScalarToken:()=>xy,isCollection:()=>RL,isScalar:()=>NL,prettyToken:()=>FL,resolveAsScalar:()=>wy,setScalarValue:()=>Ly,stringify:()=>Ey,tokenType:()=>Pu,visit:()=>Li});function wy(n,t=!0,e){if(n){let i=(r,s,a)=>{let o=typeof r=="number"?r:Array.isArray(r)?r[0]:r.offset;if(e)e(o,s,a);else throw new tt([o,o+1],s,a)};switch(n.type){case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":return Ql(n,t,i);case"block-scalar":return Gl({options:{strict:t}},n,i)}}return null}function xy(n,t){let{implicitKey:e=!1,indent:i,inFlow:r=!1,offset:s=-1,type:a="PLAIN"}=t,o=Jn({type:a,value:n},{implicitKey:e,indent:i>0?" ".repeat(i):"",inFlow:r,options:{blockQuote:!0,lineWidth:-1}}),l=t.end??[{type:"newline",offset:-1,indent:i,source:`
`}];switch(o[0]){case"|":case">":{let c=o.indexOf(`
`),u=o.substring(0,c),d=o.substring(c+1)+`
`,m=[{type:"block-scalar-header",offset:s,indent:i,source:u}];return Sy(m,l)||m.push({type:"newline",offset:-1,indent:i,source:`
`}),{type:"block-scalar",offset:s,indent:i,props:m,source:d}}case'"':return{type:"double-quoted-scalar",offset:s,indent:i,source:o,end:l};case"'":return{type:"single-quoted-scalar",offset:s,indent:i,source:o,end:l};default:return{type:"scalar",offset:s,indent:i,source:o,end:l}}}function Ly(n,t,e={}){let{afterKey:i=!1,implicitKey:r=!1,inFlow:s=!1,type:a}=e,o="indent"in n?n.indent:null;if(i&&typeof o=="number"&&(o+=2),!a)switch(n.type){case"single-quoted-scalar":a="QUOTE_SINGLE";break;case"double-quoted-scalar":a="QUOTE_DOUBLE";break;case"block-scalar":{let c=n.props[0];if(c.type!=="block-scalar-header")throw new Error("Invalid block scalar header");a=c.source[0]===">"?"BLOCK_FOLDED":"BLOCK_LITERAL";break}default:a="PLAIN"}let l=Jn({type:a,value:t},{implicitKey:r||o===null,indent:o!==null&&o>0?" ".repeat(o):"",inFlow:s,options:{blockQuote:!0,lineWidth:-1}});switch(l[0]){case"|":case">":CL(n,l);break;case'"':_u(n,l,"double-quoted-scalar");break;case"'":_u(n,l,"single-quoted-scalar");break;default:_u(n,l,"scalar")}}function CL(n,t){let e=t.indexOf(`
`),i=t.substring(0,e),r=t.substring(e+1)+`
`;if(n.type==="block-scalar"){let s=n.props[0];if(s.type!=="block-scalar-header")throw new Error("Invalid block scalar header");s.source=i,n.source=r}else{let{offset:s}=n,a="indent"in n?n.indent:-1,o=[{type:"block-scalar-header",offset:s,indent:a,source:i}];Sy(o,"end"in n?n.end:void 0)||o.push({type:"newline",offset:-1,indent:a,source:`
`});for(let l of Object.keys(n))l!=="type"&&l!=="offset"&&delete n[l];Object.assign(n,{type:"block-scalar",indent:a,props:o,source:r})}}function Sy(n,t){if(t)for(let e of t)switch(e.type){case"space":case"comment":n.push(e);break;case"newline":return n.push(e),!0}return!1}function _u(n,t,e){switch(n.type){case"scalar":case"double-quoted-scalar":case"single-quoted-scalar":n.type=e,n.source=t;break;case"block-scalar":{let i=n.props.slice(1),r=t.length;n.props[0].type==="block-scalar-header"&&(r-=n.props[0].source.length);for(let s of i)s.offset+=r;delete n.props,Object.assign(n,{type:e,source:t,end:i});break}case"block-map":case"block-seq":{let r={type:"newline",offset:n.offset+t.length,indent:n.indent,source:`
`};delete n.items,Object.assign(n,{type:e,source:t,end:[r]});break}default:{let i="indent"in n?n.indent:-1,r="end"in n&&Array.isArray(n.end)?n.end.filter(s=>s.type==="space"||s.type==="comment"||s.type==="newline"):[];for(let s of Object.keys(n))s!=="type"&&s!=="offset"&&delete n[s];Object.assign(n,{type:e,indent:i,source:t,end:r})}}}var Ey=n=>"type"in n?Xl(n):Zl(n);function Xl(n){switch(n.type){case"block-scalar":{let t="";for(let e of n.props)t+=Xl(e);return t+n.source}case"block-map":case"block-seq":{let t="";for(let e of n.items)t+=Zl(e);return t}case"flow-collection":{let t=n.start.source;for(let e of n.items)t+=Zl(e);for(let e of n.end)t+=e.source;return t}case"document":{let t=Zl(n);if(n.end)for(let e of n.end)t+=e.source;return t}default:{let t=n.source;if("end"in n&&n.end)for(let e of n.end)t+=e.source;return t}}}function Zl({start:n,key:t,sep:e,value:i}){let r="";for(let s of n)r+=s.source;if(t&&(r+=Xl(t)),e)for(let s of e)r+=s.source;return i&&(r+=Xl(i)),r}var Ku=Symbol("break visit"),IL=Symbol("skip children"),Ty=Symbol("remove item");function Li(n,t){"type"in n&&n.type==="document"&&(n={start:n.start,value:n.value}),My(Object.freeze([]),n,t)}Li.BREAK=Ku;Li.SKIP=IL;Li.REMOVE=Ty;Li.itemAtPath=(n,t)=>{let e=n;for(let[i,r]of t){let s=e?.[i];if(s&&"items"in s)e=s.items[r];else return}return e};Li.parentCollection=(n,t)=>{let e=Li.itemAtPath(n,t.slice(0,-1)),i=t[t.length-1][0],r=e?.[i];if(r&&"items"in r)return r;throw new Error("Parent collection not found")};function My(n,t,e){let i=e(t,n);if(typeof i=="symbol")return i;for(let r of["key","value"]){let s=t[r];if(s&&"items"in s){for(let a=0;a<s.items.length;++a){let o=My(Object.freeze(n.concat([[r,a]])),s.items[a],e);if(typeof o=="number")a=o-1;else{if(o===Ku)return Ku;o===Ty&&(s.items.splice(a,1),a-=1)}}typeof i=="function"&&r==="key"&&(i=i(t,n))}}return typeof i=="function"?i(t,n):i}var ao="\uFEFF",oo="",lo="",cs="",RL=n=>!!n&&"items"in n,NL=n=>!!n&&(n.type==="scalar"||n.type==="single-quoted-scalar"||n.type==="double-quoted-scalar"||n.type==="block-scalar");function FL(n){switch(n){case ao:return"<BOM>";case oo:return"<DOC>";case lo:return"<FLOW_END>";case cs:return"<SCALAR>";default:return JSON.stringify(n)}}function Pu(n){switch(n){case ao:return"byte-order-mark";case oo:return"doc-mode";case lo:return"flow-error-end";case cs:return"scalar";case"---":return"doc-start";case"...":return"doc-end";case"":case`
`:case`\r
`:return"newline";case"-":return"seq-item-ind";case"?":return"explicit-key-ind";case":":return"map-value-ind";case"{":return"flow-map-start";case"}":return"flow-map-end";case"[":return"flow-seq-start";case"]":return"flow-seq-end";case",":return"comma"}switch(n[0]){case" ":case" ":return"space";case"#":return"comment";case"%":return"directive-line";case"*":return"alias";case"&":return"anchor";case"!":return"tag";case"'":return"single-quoted-scalar";case'"':return"double-quoted-scalar";case"|":case">":return"block-scalar-header"}return null}function bn(n){switch(n){case void 0:case" ":case`
`:case"\r":case" ":return!0;default:return!1}}var Oy=new Set("0123456789ABCDEFabcdef"),BL=new Set("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-#;/?:@&=+$_.!~*'()"),tc=new Set(",[]{}"),DL=new Set(` ,[]{}
\r `),zu=n=>!n||DL.has(n),co=class{constructor(){this.atEnd=!1,this.blockScalarIndent=-1,this.blockScalarKeep=!1,this.buffer="",this.flowKey=!1,this.flowLevel=0,this.indentNext=0,this.indentValue=0,this.lineEndPos=null,this.next=null,this.pos=0}*lex(t,e=!1){if(t){if(typeof t!="string")throw TypeError("source is not a string");this.buffer=this.buffer?this.buffer+t:t,this.lineEndPos=null}this.atEnd=!e;let i=this.next??"stream";for(;i&&(e||this.hasChars(1));)i=yield*this.parseNext(i)}atLineEnd(){let t=this.pos,e=this.buffer[t];for(;e===" "||e===" ";)e=this.buffer[++t];return!e||e==="#"||e===`
`?!0:e==="\r"?this.buffer[t+1]===`
`:!1}charAt(t){return this.buffer[this.pos+t]}continueScalar(t){let e=this.buffer[t];if(this.indentNext>0){let i=0;for(;e===" ";)e=this.buffer[++i+t];if(e==="\r"){let r=this.buffer[i+t+1];if(r===`
`||!r&&!this.atEnd)return t+i+1}return e===`
`||i>=this.indentNext||!e&&!this.atEnd?t+i:-1}if(e==="-"||e==="."){let i=this.buffer.substr(t,3);if((i==="---"||i==="...")&&bn(this.buffer[t+3]))return-1}return t}getLine(){let t=this.lineEndPos;return(typeof t!="number"||t!==-1&&t<this.pos)&&(t=this.buffer.indexOf(`
`,this.pos),this.lineEndPos=t),t===-1?this.atEnd?this.buffer.substring(this.pos):null:(this.buffer[t-1]==="\r"&&(t-=1),this.buffer.substring(this.pos,t))}hasChars(t){return this.pos+t<=this.buffer.length}setNext(t){return this.buffer=this.buffer.substring(this.pos),this.pos=0,this.lineEndPos=null,this.next=t,null}peek(t){return this.buffer.substr(this.pos,t)}*parseNext(t){switch(t){case"stream":return yield*this.parseStream();case"line-start":return yield*this.parseLineStart();case"block-start":return yield*this.parseBlockStart();case"doc":return yield*this.parseDocument();case"flow":return yield*this.parseFlowCollection();case"quoted-scalar":return yield*this.parseQuotedScalar();case"block-scalar":return yield*this.parseBlockScalar();case"plain-scalar":return yield*this.parsePlainScalar()}}*parseStream(){let t=this.getLine();if(t===null)return this.setNext("stream");if(t[0]===ao&&(yield*this.pushCount(1),t=t.substring(1)),t[0]==="%"){let e=t.length,i=t.indexOf("#");for(;i!==-1;){let s=t[i-1];if(s===" "||s===" "){e=i-1;break}else i=t.indexOf("#",i+1)}for(;;){let s=t[e-1];if(s===" "||s===" ")e-=1;else break}let r=(yield*this.pushCount(e))+(yield*this.pushSpaces(!0));return yield*this.pushCount(t.length-r),this.pushNewline(),"stream"}if(this.atLineEnd()){let e=yield*this.pushSpaces(!0);return yield*this.pushCount(t.length-e),yield*this.pushNewline(),"stream"}return yield oo,yield*this.parseLineStart()}*parseLineStart(){let t=this.charAt(0);if(!t&&!this.atEnd)return this.setNext("line-start");if(t==="-"||t==="."){if(!this.atEnd&&!this.hasChars(4))return this.setNext("line-start");let e=this.peek(3);if((e==="---"||e==="...")&&bn(this.charAt(3)))return yield*this.pushCount(3),this.indentValue=0,this.indentNext=0,e==="---"?"doc":"stream"}return this.indentValue=yield*this.pushSpaces(!1),this.indentNext>this.indentValue&&!bn(this.charAt(1))&&(this.indentNext=this.indentValue),yield*this.parseBlockStart()}*parseBlockStart(){let[t,e]=this.peek(2);if(!e&&!this.atEnd)return this.setNext("block-start");if((t==="-"||t==="?"||t===":")&&bn(e)){let i=(yield*this.pushCount(1))+(yield*this.pushSpaces(!0));return this.indentNext=this.indentValue+1,this.indentValue+=i,"block-start"}return"doc"}*parseDocument(){yield*this.pushSpaces(!0);let t=this.getLine();if(t===null)return this.setNext("doc");let e=yield*this.pushIndicators();switch(t[e]){case"#":yield*this.pushCount(t.length-e);case void 0:return yield*this.pushNewline(),yield*this.parseLineStart();case"{":case"[":return yield*this.pushCount(1),this.flowKey=!1,this.flowLevel=1,"flow";case"}":case"]":return yield*this.pushCount(1),"doc";case"*":return yield*this.pushUntil(zu),"doc";case'"':case"'":return yield*this.parseQuotedScalar();case"|":case">":return e+=yield*this.parseBlockScalarHeader(),e+=yield*this.pushSpaces(!0),yield*this.pushCount(t.length-e),yield*this.pushNewline(),yield*this.parseBlockScalar();default:return yield*this.parsePlainScalar()}}*parseFlowCollection(){let t,e,i=-1;do t=yield*this.pushNewline(),t>0?(e=yield*this.pushSpaces(!1),this.indentValue=i=e):e=0,e+=yield*this.pushSpaces(!0);while(t+e>0);let r=this.getLine();if(r===null)return this.setNext("flow");if((i!==-1&&i<this.indentNext&&r[0]!=="#"||i===0&&(r.startsWith("---")||r.startsWith("..."))&&bn(r[3]))&&!(i===this.indentNext-1&&this.flowLevel===1&&(r[0]==="]"||r[0]==="}")))return this.flowLevel=0,yield lo,yield*this.parseLineStart();let s=0;for(;r[s]===",";)s+=yield*this.pushCount(1),s+=yield*this.pushSpaces(!0),this.flowKey=!1;switch(s+=yield*this.pushIndicators(),r[s]){case void 0:return"flow";case"#":return yield*this.pushCount(r.length-s),"flow";case"{":case"[":return yield*this.pushCount(1),this.flowKey=!1,this.flowLevel+=1,"flow";case"}":case"]":return yield*this.pushCount(1),this.flowKey=!0,this.flowLevel-=1,this.flowLevel?"flow":"doc";case"*":return yield*this.pushUntil(zu),"flow";case'"':case"'":return this.flowKey=!0,yield*this.parseQuotedScalar();case":":{let a=this.charAt(1);if(this.flowKey||bn(a)||a===",")return this.flowKey=!1,yield*this.pushCount(1),yield*this.pushSpaces(!0),"flow"}default:return this.flowKey=!1,yield*this.parsePlainScalar()}}*parseQuotedScalar(){let t=this.charAt(0),e=this.buffer.indexOf(t,this.pos+1);if(t==="'")for(;e!==-1&&this.buffer[e+1]==="'";)e=this.buffer.indexOf("'",e+2);else for(;e!==-1;){let s=0;for(;this.buffer[e-1-s]==="\\";)s+=1;if(s%2===0)break;e=this.buffer.indexOf('"',e+1)}let i=this.buffer.substring(0,e),r=i.indexOf(`
`,this.pos);if(r!==-1){for(;r!==-1;){let s=this.continueScalar(r+1);if(s===-1)break;r=i.indexOf(`
`,s)}r!==-1&&(e=r-(i[r-1]==="\r"?2:1))}if(e===-1){if(!this.atEnd)return this.setNext("quoted-scalar");e=this.buffer.length}return yield*this.pushToIndex(e+1,!1),this.flowLevel?"flow":"doc"}*parseBlockScalarHeader(){this.blockScalarIndent=-1,this.blockScalarKeep=!1;let t=this.pos;for(;;){let e=this.buffer[++t];if(e==="+")this.blockScalarKeep=!0;else if(e>"0"&&e<="9")this.blockScalarIndent=Number(e)-1;else if(e!=="-")break}return yield*this.pushUntil(e=>bn(e)||e==="#")}*parseBlockScalar(){let t=this.pos-1,e=0,i;e:for(let s=this.pos;i=this.buffer[s];++s)switch(i){case" ":e+=1;break;case`
`:t=s,e=0;break;case"\r":{let a=this.buffer[s+1];if(!a&&!this.atEnd)return this.setNext("block-scalar");if(a===`
`)break}default:break e}if(!i&&!this.atEnd)return this.setNext("block-scalar");if(e>=this.indentNext){this.blockScalarIndent===-1?this.indentNext=e:this.indentNext=this.blockScalarIndent+(this.indentNext===0?1:this.indentNext);do{let s=this.continueScalar(t+1);if(s===-1)break;t=this.buffer.indexOf(`
`,s)}while(t!==-1);if(t===-1){if(!this.atEnd)return this.setNext("block-scalar");t=this.buffer.length}}let r=t+1;for(i=this.buffer[r];i===" ";)i=this.buffer[++r];if(i===" "){for(;i===" "||i===" "||i==="\r"||i===`
`;)i=this.buffer[++r];t=r-1}else if(!this.blockScalarKeep)do{let s=t-1,a=this.buffer[s];a==="\r"&&(a=this.buffer[--s]);let o=s;for(;a===" ";)a=this.buffer[--s];if(a===`
`&&s>=this.pos&&s+1+e>o)t=s;else break}while(!0);return yield cs,yield*this.pushToIndex(t+1,!0),yield*this.parseLineStart()}*parsePlainScalar(){let t=this.flowLevel>0,e=this.pos-1,i=this.pos-1,r;for(;r=this.buffer[++i];)if(r===":"){let s=this.buffer[i+1];if(bn(s)||t&&tc.has(s))break;e=i}else if(bn(r)){let s=this.buffer[i+1];if(r==="\r"&&(s===`
`?(i+=1,r=`
`,s=this.buffer[i+1]):e=i),s==="#"||t&&tc.has(s))break;if(r===`
`){let a=this.continueScalar(i+1);if(a===-1)break;i=Math.max(i,a-2)}}else{if(t&&tc.has(r))break;e=i}return!r&&!this.atEnd?this.setNext("plain-scalar"):(yield cs,yield*this.pushToIndex(e+1,!0),t?"flow":"doc")}*pushCount(t){return t>0?(yield this.buffer.substr(this.pos,t),this.pos+=t,t):0}*pushToIndex(t,e){let i=this.buffer.slice(this.pos,t);return i?(yield i,this.pos+=i.length,i.length):(e&&(yield""),0)}*pushIndicators(){let t=0;e:for(;;){switch(this.charAt(0)){case"!":t+=yield*this.pushTag(),t+=yield*this.pushSpaces(!0);continue e;case"&":t+=yield*this.pushUntil(zu),t+=yield*this.pushSpaces(!0);continue e;case"-":case"?":case":":{let e=this.flowLevel>0,i=this.charAt(1);if(bn(i)||e&&tc.has(i)){e?this.flowKey&&(this.flowKey=!1):this.indentNext=this.indentValue+1,t+=yield*this.pushCount(1),t+=yield*this.pushSpaces(!0);continue e}}}break e}return t}*pushTag(){if(this.charAt(1)==="<"){let t=this.pos+2,e=this.buffer[t];for(;!bn(e)&&e!==">";)e=this.buffer[++t];return yield*this.pushToIndex(e===">"?t+1:t,!1)}else{let t=this.pos+1,e=this.buffer[t];for(;e;)if(BL.has(e))e=this.buffer[++t];else if(e==="%"&&Oy.has(this.buffer[t+1])&&Oy.has(this.buffer[t+2]))e=this.buffer[t+=3];else break;return yield*this.pushToIndex(t,!1)}}*pushNewline(){let t=this.buffer[this.pos];return t===`
`?yield*this.pushCount(1):t==="\r"&&this.charAt(1)===`
`?yield*this.pushCount(2):0}*pushSpaces(t){let e=this.pos-1,i;do i=this.buffer[++e];while(i===" "||t&&i===" ");let r=e-this.pos;return r>0&&(yield this.buffer.substr(this.pos,r),this.pos=e),r}*pushUntil(t){let e=this.pos,i=this.buffer[e];for(;!t(i);)i=this.buffer[++e];return yield*this.pushToIndex(e,!1)}};var uo=class{constructor(){this.lineStarts=[],this.addNewLine=t=>this.lineStarts.push(t),this.linePos=t=>{let e=0,i=this.lineStarts.length;for(;e<i;){let s=e+i>>1;this.lineStarts[s]<t?e=s+1:i=s}if(this.lineStarts[e]===t)return{line:e+1,col:1};if(e===0)return{line:0,col:t};let r=this.lineStarts[e-1];return{line:e,col:t-r+1}}}};function Si(n,t){for(let e=0;e<n.length;++e)if(n[e].type===t)return!0;return!1}function Cy(n){for(let t=0;t<n.length;++t)switch(n[t].type){case"space":case"comment":case"newline":break;default:return t}return-1}function Ry(n){switch(n?.type){case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":case"flow-collection":return!0;default:return!1}}function nc(n){switch(n.type){case"document":return n.start;case"block-map":{let t=n.items[n.items.length-1];return t.sep??t.start}case"block-seq":return n.items[n.items.length-1].start;default:return[]}}function ds(n){if(n.length===0)return[];let t=n.length;e:for(;--t>=0;)switch(n[t].type){case"doc-start":case"explicit-key-ind":case"map-value-ind":case"seq-item-ind":case"newline":break e}for(;n[++t]?.type==="space";);return n.splice(t,n.length)}function ic(n,t){if(t.length<1e5)Array.prototype.push.apply(n,t);else for(let e=0;e<t.length;++e)n.push(t[e])}function Iy(n){if(n.start.type==="flow-seq-start")for(let t of n.items)t.sep&&!t.value&&!Si(t.start,"explicit-key-ind")&&!Si(t.sep,"map-value-ind")&&(t.key&&(t.value=t.key),delete t.key,Ry(t.value)?t.value.end?ic(t.value.end,t.sep):t.value.end=t.sep:ic(t.start,t.sep),delete t.sep)}var mo=class{constructor(t){this.atNewLine=!0,this.atScalar=!1,this.indent=0,this.offset=0,this.onKeyLine=!1,this.stack=[],this.source="",this.type="",this.lexer=new co,this.onNewLine=t}*parse(t,e=!1){this.onNewLine&&this.offset===0&&this.onNewLine(0);for(let i of this.lexer.lex(t,e))yield*this.next(i);e||(yield*this.end())}*next(t){if(this.source=t,this.atScalar){this.atScalar=!1,yield*this.step(),this.offset+=t.length;return}let e=Pu(t);if(e)if(e==="scalar")this.atNewLine=!1,this.atScalar=!0,this.type="scalar";else{switch(this.type=e,yield*this.step(),e){case"newline":this.atNewLine=!0,this.indent=0,this.onNewLine&&this.onNewLine(this.offset+t.length);break;case"space":this.atNewLine&&t[0]===" "&&(this.indent+=t.length);break;case"explicit-key-ind":case"map-value-ind":case"seq-item-ind":this.atNewLine&&(this.indent+=t.length);break;case"doc-mode":case"flow-error-end":return;default:this.atNewLine=!1}this.offset+=t.length}else{let i=`Not a YAML token: ${t}`;yield*this.pop({type:"error",offset:this.offset,message:i,source:t}),this.offset+=t.length}}*end(){for(;this.stack.length>0;)yield*this.pop()}get sourceToken(){return{type:this.type,offset:this.offset,indent:this.indent,source:this.source}}*step(){let t=this.peek(1);if(this.type==="doc-end"&&t?.type!=="doc-end"){for(;this.stack.length>0;)yield*this.pop();this.stack.push({type:"doc-end",offset:this.offset,source:this.source});return}if(!t)return yield*this.stream();switch(t.type){case"document":return yield*this.document(t);case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":return yield*this.scalar(t);case"block-scalar":return yield*this.blockScalar(t);case"block-map":return yield*this.blockMap(t);case"block-seq":return yield*this.blockSequence(t);case"flow-collection":return yield*this.flowCollection(t);case"doc-end":return yield*this.documentEnd(t)}yield*this.pop()}peek(t){return this.stack[this.stack.length-t]}*pop(t){let e=t??this.stack.pop();if(!e)yield{type:"error",offset:this.offset,source:"",message:"Tried to pop an empty stack"};else if(this.stack.length===0)yield e;else{let i=this.peek(1);switch(e.type==="block-scalar"?e.indent="indent"in i?i.indent:0:e.type==="flow-collection"&&i.type==="document"&&(e.indent=0),e.type==="flow-collection"&&Iy(e),i.type){case"document":i.value=e;break;case"block-scalar":i.props.push(e);break;case"block-map":{let r=i.items[i.items.length-1];if(r.value){i.items.push({start:[],key:e,sep:[]}),this.onKeyLine=!0;return}else if(r.sep)r.value=e;else{Object.assign(r,{key:e,sep:[]}),this.onKeyLine=!r.explicitKey;return}break}case"block-seq":{let r=i.items[i.items.length-1];r.value?i.items.push({start:[],value:e}):r.value=e;break}case"flow-collection":{let r=i.items[i.items.length-1];!r||r.value?i.items.push({start:[],key:e,sep:[]}):r.sep?r.value=e:Object.assign(r,{key:e,sep:[]});return}default:yield*this.pop(),yield*this.pop(e)}if((i.type==="document"||i.type==="block-map"||i.type==="block-seq")&&(e.type==="block-map"||e.type==="block-seq")){let r=e.items[e.items.length-1];r&&!r.sep&&!r.value&&r.start.length>0&&Cy(r.start)===-1&&(e.indent===0||r.start.every(s=>s.type!=="comment"||s. Line truncated
`)+1;for(;e!==0;)this.onNewLine(this.offset+e),e=this.source.indexOf(`
`,e)+1}yield*this.pop();break;default:yield*this.pop(),yield*this.step()}}*blockMap(t){let e=t.items[t.items.length-1];switch(this.type){case"newline":if(this.onKeyLine=!1,e.value){let i="end"in e.value?e.value.end:void 0;(Array.isArray(i)?i[i.length-1]:void 0)?.type==="comment"?i?.push(this.sourceToken):t.items.push({start:[this.sourceToken]})}else e.sep?e.sep.push(this.sourceToken):e.start.push(this.sourceToken);return;case"space":case"comment":if(e.value)t.items.push({start:[this.sourceToken]});else if(e.sep)e.sep.push(this.sourceToken);else{if(this.atIndentedComment(e.start,t.indent)){let r=t.items[t.items.length-2]?.value?.end;if(Array.isArray(r)){ic(r,e.start),r.push(this.sourceToken),t.items.pop();return}}e.start.push(this.sourceToken)}return}if(this.indent>=t.indent){let i=!this.onKeyLine&&this.indent===t.indent,r=i&&(e.sep||e.explicitKey)&&this.type!=="seq-item-ind",s=[];if(r&&e.sep&&!e.value){let a=[];for(let o=0;o<e.sep.length;++o){let l=e.sep[o];switch(l.type){case"newline":a.push(o);break;case"space":break;case"comment":l.indent>t.indent&&(a.length=0);break;default:a.length=0}}a.length>=2&&(s=e.sep.splice(a[1]))}switch(this.type){case"anchor":case"tag":r||e.value?(s.push(this.sourceToken),t.items.push({start:s}),this.onKeyLine=!0):e.sep?e.sep.push(this.sourceToken):e.start.push(this.sourceToken);return;case"explicit-key-ind":!e.sep&&!e.explicitKey?(e.start.push(this.sourceToken),e.explicitKey=!0):r||e.value?(s.push(this.sourceToken),t.items.push({start:s,explicitKey:!0})):this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:[this.sourceToken],explicitKey:!0}]}),this.onKeyLine=!0;return;case"map-value-ind":if(e.explicitKey)if(e.sep)if(e.value)t.items.push({start:[],key:null,sep:[this.sourceToken]});else if(Si(e.sep,"map-value-ind"))this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:s,key:null,sep:[this.sourceToken]}]});else if(Ry(e.key)&&!Si(e.sep,"newline")){let a=ds(e.start),o=e.key,l=e.sep;l.push(this.sourceToken),delete e.key,delete e.sep,this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:a,key:o,sep:l}]})}else s.length>0?e.sep=e.sep.concat(s,this.sourceToken):e.sep.push(this.sourceToken);else if(Si(e.start,"newline"))Object.assign(e,{key:null,sep:[this.sourceToken]});else{let a=ds(e.start);this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:a,key:null,sep:[this.sourceToken]}]})}else e.sep?e.value||r?t.items.push({start:s,key:null,sep:[this.sourceToken]}):Si(e.sep,"map-value-ind")?this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:[],key:null,sep:[this.sourceToken]}]}):e.sep.push(this.sourceToken):Object.assign(e,{key:null,sep:[this.sourceToken]});this.onKeyLine=!0;return;case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":{let a=this.flowScalar(this.type);r||e.value?(t.items.push({start:s,key:a,sep:[]}),this.onKeyLine=!0):e.sep?this.stack.push(a):(Object.assign(e,{key:a,sep:[]}),this.onKeyLine=!0);return}default:{let a=this.startBlockValue(t);if(a){if(a.type==="block-seq"){if(!e.explicitKey&&e.sep&&!Si(e.sep,"newline")){yield*this.pop({type:"error",offset:this.offset,message:"Unexpected block-seq-ind on same line with key",source:this.source});return}}else i&&t.items.push({start:s});this.stack.push(a);return}}}}yield*this.pop(),yield*this.step()}*blockSequence(t){let e=t.items[t.items.length-1];switch(this.type){case"newline":if(e.value){let i="end"in e.value?e.value.end:void 0;(Array.isArray(i)?i[i.length-1]:void 0)?.type==="comment"?i?.push(this.sourceToken):t.items.push({start:[this.sourceToken]})}else e.start.push(this.sourceToken);return;case"space":case"comment":if(e.value)t.items.push({start:[this.sourceToken]});else{if(this.atIndentedComment(e.start,t.indent)){let r=t.items[t.items.length-2]?.value?.end;if(Array.isArray(r)){ic(r,e.start),r.push(this.sourceToken),t.items.pop();return}}e.start.push(this.sourceToken)}return;case"anchor":case"tag":if(e.value||this.indent<=t.indent)break;e.start.push(this.sourceToken);return;case"seq-item-ind":if(this.indent!==t.indent)break;e.value||Si(e.start,"seq-item-ind")?t.items.push({start:[this.sourceToken]}):e.start.push(this.sourceToken);return}if(this.indent>t.indent){let i=this.startBlockValue(t);if(i){this.stack.push(i);return}}yield*this.pop(),yield*this.step()}*flowCollection(t){let e=t.items[t.items.length-1];if(this.type==="flow-error-end"){let i;do yield*this.pop(),i=this.peek(1);while(i?.type==="flow-collection")}else if(t.end.length===0){switch(this.type){case"comma":case"explicit-key-ind":!e||e.sep?t.items.push({start:[this.sourceToken]}):e.start.push(this.sourceToken);return;case"map-value-ind":!e||e.value?t.items.push({start:[],key:null,sep:[this.sourceToken]}):e.sep?e.sep.push(this.sourceToken):Object.assign(e,{key:null,sep:[this.sourceToken]});return;case"space":case"comment":case"newline":case"anchor":case"tag":!e||e.value?t.items.p Line truncated
`)+1;for(;e!==0;)this.onNewLine(this.offset+e),e=this.source.indexOf(`
`,e)+1}return{type:t,offset:this.offset,indent:this.indent,source:this.source}}startBlockValue(t){switch(this.type){case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":return this.flowScalar(this.type);case"block-scalar-header":return{type:"block-scalar",offset:this.offset,indent:this.indent,props:[this.sourceToken],source:""};case"flow-map-start":case"flow-seq-start":return{type:"flow-collection",offset:this.offset,indent:this.indent,start:this.sourceToken,items:[],end:[]};case"seq-item-ind":return{type:"block-seq",offset:this.offset,indent:this.indent,items:[{start:[this.sourceToken]}]};case"explicit-key-ind":{this.onKeyLine=!0;let e=nc(t),i=ds(e);return i.push(this.sourceToken),{type:"block-map",offset:this.offset,indent:this.indent,items:[{start:i,explicitKey:!0}]}}case"map-value-ind":{this.onKeyLine=!0;let e=nc(t),i=ds(e);return{type:"block-map",offset:this.offset,indent:this.indent,items:[{start:i,key:null,sep:[this.sourceToken]}]}}}return null}atIndentedComment(t,e){return this.type!=="comment"||this.indent<=e?!1:t.every(i=>i.type==="newline"||i.type==="space")}*documentEnd(t){this.type!=="doc-mode"&&(t.end?t.end.push(this.sourceToken):t.end=[this.sourceToken],this.type==="newline"&&(yield*this.pop()))}*lineEnd(t){switch(this.type){case"comma":case"doc-start":case"doc-end":case"flow-seq-end":case"flow-map-end":case"map-value-ind":yield*this.pop(),yield*this.step();break;case"newline":this.onKeyLine=!1;default:t.end?t.end.push(this.sourceToken):t.end=[this.sourceToken],this.type==="newline"&&(yield*this.pop())}}};function YL(n){let t=n.prettyErrors!==!1;return{lineCounter:n.lineCounter||t&&new uo||null,prettyErrors:t}}function us(n,t={}){let{lineCounter:e,prettyErrors:i}=YL(t),r=new mo(e?.addNewLine),s=new so(t),a=null;for(let o of s.compose(r.parse(n),!0,n.length))if(!a)a=o;else if(a.options.logLevel!=="silent"){a.errors.push(new tt(o.range.slice(0,2),"MULTIPLE_DOCS","Source contains multiple documents; please use YAML.parseAllDocuments()"));break}return i&&e&&(a.errors.forEach(Ru(n,e)),a.warnings.forEach(Ru(n,e))),a}function kn(n,t,e){let i;typeof t=="function"?i=t:e===void 0&&t&&typeof t=="object"&&(e=t);let r=us(n,e);if(!r)return null;if(r.warnings.forEach(s=>Cl(r.options.logLevel,s)),r.errors.length>0){if(r.options.logLevel!=="silent")throw r.errors[0];r.errors=[]}return r.toJS(Object.assign({reviver:i},e))}function rc(n,t,e){let i=null;if(typeof t=="function"||Array.isArray(t)?i=t:e===void 0&&t&&(e=t),typeof e=="string"&&(e=e.length),typeof e=="number"){let r=Math.round(e);e=r<1?void 0:r>8?{indent:8}:{indent:r}}if(n===void 0){let{keepUndefined:r}=e??t??{};if(!r)return}return mn(n)&&!i?n.toString(e):new yn(n,i,e).toString(e)}var Wu="tag",Bn="tags",Ct=[Wu,Bn],KL="alias",Ti="aliases",It=[KL,Ti],ju="linter-yaml-title-alias",ms="disabled rules";function $t(n){return n.match(Ze)===null&&(n=`---
---
`+n),n}function Mi(n){let t=n.match(Ze);return t?t[1]:null}function Ee(n,t){let e=n.match(Ze);if(!e)return n;let i=e[0],r=t(i);return n=n.replace(i,ft(r)),n}function PL(n){return us(n,{keepSourceTokens:!0})}function Uu(n){if(!n||typeof n!="object")return null;let t=n;return t.range&&typeof t.range[0]=="number"?t.range[0]:t.srcToken&&typeof t.srcToken.start=="number"?t.srcToken.start:null}function zL(n){if(!n||typeof n!="object")return null;let t=n;return t.range&&typeof t.range[1]=="number"?t.range[1]:t.srcToken&&typeof t.srcToken.end=="number"?t.srcToken.end:null}function qL(n){if(typeof n!="string")return null;let t=n.trim();return t.length>=2&&(t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'"))?t.substring(1,t.length-1):t}function Fy(n,t,e){let i=qL(t);if(i==null)return null;for(let r of n.items){let s=r;if((s.key&&typeof s.key.value=="string"?s.key.value:null)===i)return s;if(e&&s.value&&ht(s.value)){let o=Fy(s.value,t,!0);if(o)return o}}return null}function Hu(n,t,e){if(typeof t!="string")return null;let i=PL(n);return!i.contents||!ht(i.contents)?null:Fy(i.contents,t,e)}function $u(n,t){let e=n.lastIndexOf(`
`,t-1);return e===-1?0:e+1}function qu(n,t){let e=n.indexOf(`
`,t);return e===-1?n.length:e}function WL(n,t){let e=null;for(let i=t;i<n.length;i++){let r=n[i];if(e!==null){r===e&&(e==='"'&&n[i-1]!=="\\"?e=null:e==="'"&&n[i+1]==="'"?i++:e==="'"&&(e=null));continue}if(r==='"'||r==="'"){e=r;continue}if(r===":")return i}return-1}function By(n,t){let e=Uu(t.key);if(e==null)return null;let i=$u(n,e),r=qu(n,e),s=n.substring(i,r),a=e-i,o=WL(s,a);if(o===-1)return null;let l=i+o;return{start:e,end:l,colon:l}}function Dy(n,t){let e=By(n,t);if(!e)return null;let i=e.colon+1,r=qu(n,e.colon);for(;i<r&&(n[i]===" "||n[i]===" ");)i++;let s=Uu(t.value),a=zL(t.value);if(s==null||a==null)return{start:i,end:r};let o=a,l=qu(n,a),c=n.substring(a,l);return/^[ \t]*#/.test(c)&&(o=l),{start:i,end:o}}function Yy(n,t){let e=Uu(t.key),i=Dy(n,t);if(e==null||i==null)return null;let r=$u(n,e),s=i.end;return n[s]===`
`&&s++,{start:r,end:s}}function Le(n,t,e=!0){let i=Hu(n,t,e);if(!i)return null;let r=Dy(n,i);return r?n.substring(r.start,r.end):null}function he(n,t,e,i=!0){let r=Hu(n,t,i);if(!r)return`${n}${t}:${e}
`;let s=Yy(n,r),a=By(n,r);if(!s||!a)return n;let o=$u(n,a.start),l=n.substring(o,a.start),c=n.substring(a.start,a.end).trimEnd(),u=`${l}${c}:${e}
`;return n.substring(0,s.start)+u+n.substring(s.end)}function po(n,t,e=!0){let i=Hu(n,t,e);if(!i)return n;let r=Yy(n,i);return r?n.substring(0,r.start)+n.substring(r.end):n}function jL(n){let t=us(n,{keepSourceTokens:!0}),e=[];return Ut(t,(i,r)=>{r instanceof W&&(r.type!=="BLOCK_LITERAL"&&r.type!=="BLOCK_FOLDED"||r.range==null||r.range.length<3||e.push({start:{line:0,column:0,offset:r.range[0]},end:{line:0,column:0,offset:r.range[2]}}))}),e}function UL(n,t,e){let i=e.start.offset??0,r=e.end.offset??0;return n<r&&t>i}function _y(n){let t=jL(n);return n.replace(Zr,(e,i)=>{let r=i,s=i+e.length;return t.some(o=>UL(r,s,o))?e:`
`})}function dt(n){if(n==null)return null;let t=kn(n.replace(/\n(\t)+/g,`
`));return t??{}}function Ky(n){if(n==null)return null;let t=us(n.replace(/\n(\t)+/g,`
`),{keepSourceTokens:!0});return t??null}function Vu(n){let t=new yn(n.options);t.contents=new Me;let e=n.contents?.srcToken;return t.contents.srcToken={offset:e.offset,type:e.type,indent:e.indent,start:e.start,end:e.end,items:[]},t}function Lr(n){if(!n||!n.contents||!n.contents.srcToken)return"";let t=n.contents.items;return!t||t.length==0?"":ec.stringify(n.contents.srcToken)}var vn=(e=>(e.SingleLine="single-line",e.MultiLine="multi-line",e))(vn||{});function Se(n,t,e,i,r=!1){if(typeof n=="string"&&(n=[n]),n==null||n.length===0)return HL(t);let s=i&&(t=="multi-line"||t=="single string to multi-line"&&n.length>1);if(r||s)for(let a=0;a<n.length;a++){let o=n[a],l=Ei(o);l&&(o=o.substring(1,o.length-1));let c=r&&Go(o);l&&c||(c||l&&s)&&(n[a]=nt(o,e,c))}switch(t){case"single string to single-line":if(n.length===1)return" "+n[0];case"single-line":for(let a=0;a<n.length;a++)n[a].includes(",")&&!Ei(n[a])&&(n[a]=nt(n[a],e,!0));return" "+Ny(n);case"single string to multi-line":if(n.length===1)return" "+n[0];case"multi-line":return $L(n);case"single string space delimited":return n.length===1?" "+n[0]:" "+n.join(" ");case"single string comma delimited":for(let a=0;a<n.length;a++)n[a].includes(",")&&!Ei(n[a])&&(n[a]=nt(n[a],e,!0));return n.length===1?" "+n[0]:" "+n.join(", ");case"single-line space delimited":return n.length===1?" "+n[0]:" "+Ny(n).replaceAll(", "," ")}}function HL(n){switch(n){case"single-line":case"single-line space delimited":case"multi-line":return" []";case"single string to single-line":case"single string to multi-line":case"single string space delimited":case"single string comma delimited":return" "}}function Ny(n){return n==null||n.length===0?"[]":"["+n.join(", ")+"]"}function $L(n){return n==null||n.length===0?"[]":`
- `+n.join(`
- `)}function Ne(n){if(n==null||n.length===0)return null;if(n=n.trimEnd(),n.startsWith("["))return n=n.substring(1),n.endsWith("]")&&(n=n.substring(0,n.length-1)),n.length===0?null:(sc(n,",")??[]).filter(e=>e!="");if(n.includes(`
`)){let t=n.split(/[ \t]*\n[ \t]*-[ \t]*/);return t.splice(0,1),t=t.filter(e=>e!=""),t==null||t.length===0?null:t}return n}function An(n){if(n==null)return[];let t=[],e;Array.isArray(n)?e=n:n.includes(",")?e=sc(n,",")??[]:e=sc(n," ")??[];for(let i of e)t.push(i.trim());return t}function wn(n){return typeof n=="string"?sc(n,",")??[]:n}function sc(n,t=","){if(n==""||n==null)return null;if(t.length>1)throw new Error(A("logs.invalid-delimiter-error-message"));let e=[],i="",r=0;for(;r<n.length;){let s=n.charAt(r);if(s===t)e.push(i.trim()),i="";else if(s==='"'||s==="'"){let a=n.indexOf(s,r+1);a!=-1?(i+=n.substring(r,a+1),r=a):i+=s}else i+=s;r++}return i.trim()!=""&&e.push(i.trim()),e}function Ei(n){return n.length>1&&(n.startsWith("'")&&n.endsWith("'")||n.startsWith('"')&&n.endsWith('"'))}function nt(n,t,e=!1,i=!1){let r=VL(n,t,e);if(i)return r;try{if(kn(r,{logLevel:"error"})===n)return r}catch{}let s=rc(n,{lineWidth:-1,quotingType:t,forceQuotes:e}).slice(0,-1),a=rc(n,{lineWidth:-1,quotingType:t=='"'?"'":'"',forceQuotes:e}).slice(0,-1);return a===n||a.length<s.length?a:s}function VL(n,t,e=!1){if(Ei(n))return n;let i=n.includes("'"),r=n.includes('"'),s=n.includes(": ");return!i&&!r&&!s&&!e||i&&r?n:i?`"${n}"`:r?`'${n}'`:`${t}${n}${t}`}function Py(n){let t=Le(n,ms);if(t==null)return[];let e=t.includes(`
`)?`${ms}:
`:`${ms}: `;e+=t;let r=dt(e)["disabled rules"];return r?(typeof r=="string"&&(r=[r]),r):[]}var yc=require("obsidian");var Gu=require("obsidian");function zy(n,t){n.includes("</")?t.append((0,Gu.sanitizeHTMLToDom)(n)):t.setText(n)}function fe(n){return n.includes("</")?(0,Gu.sanitizeHTMLToDom)(n):n}var ac=require("obsidian"),fo=class extends ac.AbstractInputSuggest{constructor(e,i,r=[]){super(e,i);this.inputEl=i;this.valuesToExclude=r}getSuggestions(e){let i=this.app.vault.getAllLoadedFiles().filter(a=>a instanceof ac.TFile&&a.path.endsWith(".md")).map(a=>a.path),r=this.inputEl.getAttribute("fileName"),s=e.toLowerCase();return i.filter(a=>this.valuesToExclude.includes(a)&&a!==r?!1:a.toLowerCase().contains(s))}renderSuggestion(e,i){i.setText(e)}selectSuggestion(e,i){this.inputEl.setAttribute("fileName",e),this.setValue(e),this.inputEl.trigger("input"),this.close()}};var qy=require("obsidian");var oc=class extends qy.Modal{constructor(t,e){if(super(t),this.modalEl.addClass("confirm-modal"),this.contentEl.createEl("h3",{text:A("parse-results-heading-text"),cls:"modal-heading"}),e?.customReplacements.size>0){this.contentEl.createEl("p",{text:A("file-parse-description-text").replace("{FILE}",e.filePath)}).id="confirm-dialog";let i=this.contentEl.createDiv().createEl("table",{cls:"markdown-rendered"}),r=i.createEl("tr");r.createEl("th",{text:A("find-header-text")}),r.createEl("th",{text:A("replace-header-text")});let s;for(let a of e.customReplacements)s=i.createEl("tr"),s.createEl("td",{text:a[0]}),s.createEl("td",{text:a[1]})}else this.contentEl.createEl("p",{text:A("no-parsed-values-found-text").replaceAll("{FILE}",e.filePath),cls:"modal-warn"});this.contentEl.createDiv("modal-button-container",i=>{i.createEl("button",{text:A("close-button-text")}).addEventListener("click",()=>this.close())})}};var Vt=require("obsidian");var lc=require("obsidian"),ho=class extends lc.AbstractInputSuggest{constructor(e,i,r=[]){super(e,i);this.inputEl=i;this.valuesToExclude=r}getSuggestions(e){let i=this.app.vault.getAllLoadedFiles().filter(a=>a instanceof lc.TFolder&&a.path!=="/").map(a=>a.path),r=this.inputEl.getAttribute("folderName"),s=e.toLowerCase();return i.filter(a=>this.valuesToExclude.includes(a)&&a!==r?!1:a.toLowerCase().contains(s))}renderSuggestion(e,i){i.setText(e)}selectSuggestion(e,i){this.inputEl.setAttribute("folderName",e),this.setValue(e),this.inputEl.trigger("input"),this.close()}};var He=require("obsidian");var Qu=class{constructor(t){this.helpEl=null;this.containerEl=t.createEl("p",{cls:"form-field"}),this.labelEl=this.containerEl.createEl("label")}setName(t){return this.labelEl.setText(t),this}setHelp(t){return this.helpEl||(this.helpEl=this.containerEl.createDiv({cls:"form-field-help"})),this.helpEl.empty(),typeof t=="string"?this.helpEl.setText(t):this.helpEl.append(t),this}addText(t){let e=new He.TextComponent(this.containerEl);return t(e),this}addDropdown(t){let e=new He.DropdownComponent(this.containerEl);return t(e),this}addToggle(t){let e=new He.ToggleComponent(this.containerEl);return t(e),this}addButton(t){let e=new He.ButtonComponent(this.containerEl);return t(e),this}},Xn=class extends He.Modal{constructor(t){if(super(t),this.modalEl.addClass("mod-lg","mod-form-sheet"),He.Platform.isPhone){let e=this.headerEl;e.createDiv({cls:"modal-header-button mod-raised clickable-icon mod-start"},i=>{(0,He.setIcon)(i,"x"),i.addEventListener("click",()=>this.close())}),this.ctaEl=e.createDiv({cls:"modal-header-button mod-raised clickable-icon mod-cta"},i=>(0,He.setIcon)(i,"lucide-check")),this.ctaEl.addEventListener("click",()=>this.formSubmit())}else this.buttonContainerEl=this.modalEl.createDiv({cls:"modal-button-container"}),this.ctaButton=new He.ButtonComponent(this.buttonContainerEl).setCta().setButtonText("Save").onClick(()=>this.formSubmit()),this.ctaEl=this.ctaButton.buttonEl,new He.ButtonComponent(this.buttonContainerEl).setButtonText(A("cancel-button-text")).onClick(()=>this.close())}addField(t){let e=new Qu(this.contentEl);return t(e),e}setCtaText(t){return this.ctaButton?.setButtonText(t),this}setCtaDisabled(t){return this.ctaButton?.setDisabled(t),this.ctaEl.toggleClass("is-disabled",t),this}setCtaLoading(t){return this.ctaButton?.setLoading?.call(this.ctaButton,t),this.ctaEl.toggleClass("mod-loading",t),this}setCtaClass(t){return this.ctaEl.addClass(t),this}formSubmit(){this.onSubmit()}onSubmit(){}};var Wy=require("obsidian"),go=class extends Wy.AbstractInputSuggest{constructor(e,i,r=[],s=null){super(e,i);this.inputEl=i;this.valuesToExclude=r;s&&this.selectSuggestion(s,null)}getSuggestions(e){let i=this.app.commands.listCommands()??[],r=this.inputEl.getAttribute("commandId"),s=e.toLowerCase();return i.filter(a=>this.valuesToExclude.some(l=>l.id===a.id)&&a.id!==r?!1:a.id.contains(s)||a.name.toLowerCase().contains(s))}renderSuggestion(e,i){i.setText(e.name)}selectSuggestion(e,i){this.inputEl.setAttribute("commandId",e.id),this.setValue(e.name),this.inputEl.trigger("input"),this.close()}};var jy=" Line truncated
[ ]{`.concat(Math.min.apply(Math,r),"}"),"g");i=i.map(function(o){return o.replace(s,`
`)})}i[0]=i[0].replace(/^\r?\n/,"");var a=i[0];return t.forEach(function(o,l){var c=a.match(/(?:^|\n)( *)$/),u=c?c[1]:"",d=o;typeof o=="string"&&o.includes(`
`)&&(d=String(o).split(`
`).map(function(m,p){return p===0?m:"".concat(u).concat(m)}).join(`
`)),a+=d+i[l+1]}),a}var Gy=QL;var Ac=Sn(Ka());function Qy(n){let t=[],e=0;for(let[i,r]of n)i===Ac.default.DIFF_EQUAL?e+=r.length:i===Ac.default.DIFF_DELETE?(t.push({from:e,to:e+r.length}),e+=r.length):i===Ac.default.DIFF_INSERT&&t.push({from:e,insert:r});return t}var od=require("obsidian");var y={code:{replaceAction:"code",placeholder:"{CODE_BLOCK_PLACEHOLDER}"},inlineCode:{replaceAction:"inlineCode",placeholder:"{INLINE_CODE_BLOCK_PLACEHOLDER}"},image:{replaceAction:"image",placeholder:"{IMAGE_PLACEHOLDER}"},thematicBreak:{replaceAction:"thematicBreak",placeholder:"{HORIZONTAL_RULE_PLACEHOLDER}"},italics:{replaceAction:"emphasis",placeholder:"{ITALICS_PLACEHOLDER}"},bold:{replaceAction:"strong",placeholder:"{STRONG_PLACEHOLDER}"},list:{replaceAction:"list",placeholder:"{LIST_PLACEHOLDER}"},blockquote:{replaceAction:"blockquote",placeholder:"{BLOCKQUOTE_PLACEHOLDER}"},math:{replaceAction:"math",placeholder:"{MATH_PLACEHOLDER}"},inlineMath:{replaceAction:"inlineMath",placeholder:"{INLINE_MATH_PLACEHOLDER}"},html:{replaceAction:"html",placeholder:"{HTML_PLACEHOLDER}"},heading:{replaceAction:"heading",placeholder:"{HEADING_PLACEHOLDER}"},yaml:{replaceAction:Ze,placeholder:`---
---`},wikiLink:{replaceAction:pl,placeholder:"{WIKI_LINK_PLACEHOLDER}"},obsidianMultiLineComments:{replaceAction:Mg,placeholder:"{OBSIDIAN_COMMENT_PLACEHOLDER}"},footnoteAtStartOfLine:{replaceAction:ml,placeholder:"{FOOTNOTE_AT_START_OF_LINE_PLACEHOLDER}"},footnoteAfterATask:{replaceAction:/- \[.] (\[\^\w+\]) ?([,.;!:?])/gm,placeholder:"{FOOTNOTE_AFTER_A_TASK_PLACEHOLDER}"},url:{replaceAction:Jr,placeholder:"{URL_PLACEHOLDER}"},anchorTag:{replaceAction:Cg,placeholder:"{ANCHOR_PLACEHOLDER}"},templaterCommand:{replaceAction:Bg,placeholder:"{TEMPLATER_PLACEHOLDER}"},link:{replaceAction:"link",placeholder:"{REGULAR_LINK_PLACEHOLDER}",onlyIfMatches:Ar},tag:{placeholder:"#tag-placeholder",findRanges:JL},table:{placeholder:"{TABLE_PLACEHOLDER}",findRanges:fi},customIgnore:{placeholder:"{CUSTOM_IGNORE_PLACEHOLDER}",findRanges:gg}};function JL(n){let t=[];for(let e of n.matchAll(fl)){let i=e.index+e[1].length;t.push({startIndex:i,endIndex:i+e[2].length})}return t}var ZL=[y.customIgnore,y.obsidianMultiLineComments,y.templaterCommand,y.yaml,y.anchorTag,y.table,y.code,y.inlineCode,y.math,y.inlineMath,y.html,y.heading,y.blockquote,y.list,y.thematicBreak,y.bold,y.italics,y.image,y.link,y.wikiLink,y.tag,y.url,y.footnoteAtStartOfLine,y.footnoteAfterATask];Vf(ZL);var Jy=1e4,hs,Ao,Ci,ut=class ut{static getRule(){let t=new this;if(!v(ut,hs).has(t.alias)){let e=new bc(t.nameKey,t.descriptionKey,t.settingsKey,t.alias,t.type,t.safeApply.bind(t),t.optionBuilders.map(i=>i.option),t.hasSpecialExecutionOrder,t.ignoreTypes,t.disableConflictingOptions);v(ut,hs).set(t.alias,e),v(ut,Ao).set(t.alias,t)}return v(ut,hs).get(t.alias)}static applyIfEnabledBase(t,e,i,r,s){let a=t.getOptions(i);if(a[t.enabledOptionName()]){sr(t.alias);let o=Object.assign({},a,r);$e(`${A("logs.run-rule-text")} ${t.getName()}`);try{let l=t.apply(e,o,s);return ai(t.alias),l.length>Jy?$e(l.slice(0,Jy-1)+"..."):$e(l),[l,!0]}catch(l){ai(t.alias),vc(l instanceof Error?l:new Error(String(l)),t.getName())}}return[e,!1]}static getBuilderByName(t){return v(ut,Ao).get(t)}static setNoSettingControl(t,e){v(ut,Ci).has(t)||v(ut,Ci).set(t,[]),v(ut,Ci).get(t).push(e)}static hasSettingControl(t,e){return!v(ut,Ci).has(t)||!v(ut,Ci).get(t).includes(e)}};hs=new WeakMap,Ao=new WeakMap,Ci=new WeakMap,ee(ut,hs,new Map),ee(ut,Ao,new Map),ee(ut,Ci,new Map);var Ii=ut,w=class extends Ii{constructor(t){super(),this.alias=t.nameKey.substring(6,t.nameKey.length-5),this.settingsKey=this.alias,this.nameKey=t.nameKey,this.descriptionKey=t.descriptionKey,this.type=t.type,this.hasSpecialExecutionOrder=t.hasSpecialExecutionOrder??!1,this.disableConflictingOptions=t.disableConflictingOptions??null,t.ruleIgnoreTypes?this.ignoreTypes=[y.customIgnore,...t.ruleIgnoreTypes]:this.ignoreTypes=[y.customIgnore]}static register(t,e){let i=t.getRule();$y(i)}safeApply(t,e,i){return this.apply(t,this.buildRuleOptions(e),i)}buildRuleOptions(t){t=t??{};let e=new this.OptionsClass,i=Object.assign(e,t);for(let r of this.optionBuilders)r.setRuleOption(i,t);return i}static applyIfEnabled(t,e,i,r,s){let a=this.getRule();return i.includes(a.alias)?($e(a.alias+" "+A("logs.disabled-text")),[t,!1]):Ii.applyIfEnabledBase(a,t,e,r,s)}static getRuleOptions(t){let e=Ii.getRule.bind(this)(),i=new this,r=e.getOptions(t);return i.buildRuleOptions(r)}static noSettingControl(){return function(t,e){let i=String(e.name);e.addInitializer(function(){Ii.setNoSettingControl(this.constructor.name,i)})}}getOptionBuilderByOptionsKey(t){return this.optionBuilders.find(e=>e.optionsKey===t)}};var gs,ei=class{constructor(t){ee(this,gs);this.OptionsClass=t.OptionsClass;let e=t.nameKey.split(".");e.length==1?this.configKey=e[0]:this.configKey=e[e.length-2],this.nameKey=t.nameKey,this.descriptionKey=t.descriptionKey,this.optionsKey=t.optionsKey}get defaultValue(){return new this.OptionsClass()[this.optionsKey]}get option(){return v(this,gs)||H(this,gs,this.buildOption()),v(this,gs)}setRuleOption(t,e){let i=e[this.configKey];i!==void 0&&(t[this.optionsKey]=i)}};gs=new WeakMap;var V=class extends ei{constructor(t){super(t),this.onChange=t.onChange??null}buildOption(){return new ps(this.configKey,this.nameKey,this.descriptionKey,this.defaultValue,null,this.onChange)}},wc=class extends ei{buildOption(){return new vo(this.configKey,this.nameKey,this.descriptionKey,this.defaultValue)}},de=class extends ei{constructor(t){super(t),this.records=t.records.map(e=>new fc("enums."+e.value,e.description))}buildOption(){return new hc(this.configKey,this.nameKey,this.descriptionKey,this.defaultValue,this.records)}},Ae=class extends ei{constructor(e){super(e);this.validator=void 0;this.validator=e.validator,this.emptyStateKey=e.emptyStateKey,this.fieldNamePlaceholderKey=e.fieldNamePlaceholderKey,this.allowReorder=e.allowReorder??!1,this.trimItemWhitespace=e.trimItemWhitespace??!1}buildOption(){return new mc(this.configKey,this.nameKey,this.descriptionKey,null,this.defaultValue??[],this.validator,this.emptyStateKey,this.fieldNamePlaceholderKey,this.allowReorder,th Line truncated
`?t:t.replace(r,r+`
`)}get optionBuilders(){return[]}};Ju=I(tS),ti=O(Ju,0,"AddBlankLineAfterYAML",Zy,ti),L(Ju,1,ti);var Xu=[[0,31,"N"],[32,126,"Na"],[127,160,"N"],[161,161,"A"],[162,163,"Na"],[164,164,"A"],[165,166,"Na"],[167,168,"A"],[169,169,"N"],[170,170,"A"],[171,171,"N"],[172,172,"Na"],[173,174,"A"],[175,175,"Na"],[176,180,"A"],[181,181,"N"],[182,186,"A"],[187,187,"N"],[188,191,"A"],[192,197,"N"],[198,198,"A"],[199,207,"N"],[208,208,"A"],[209,214,"N"],[215,216,"A"],[217,221,"N"],[222,225,"A"],[226,229,"N"],[230,230,"A"],[231,231,"N"],[232,234,"A"],[235,235,"N"],[236,237,"A"],[238,239,"N"],[240,240,"A"],[241,241,"N"],[242,243,"A"],[244,246,"N"],[247,250,"A"],[251,251,"N"],[252,252,"A"],[253,253,"N"],[254,254,"A"],[255,256,"N"],[257,257,"A"],[258,272,"N"],[273,273,"A"],[274,274,"N"],[275,275,"A"],[276,282,"N"],[283,283,"A"],[284,293,"N"],[294,295,"A"],[296,298,"N"],[299,299,"A"],[300,304,"N"],[305,307,"A"],[308,311,"N"],[312,312,"A"],[313,318,"N"],[319,322,"A"],[323,323,"N"],[324,324,"A"],[325,327,"N"],[328,331,"A"],[332,332,"N"],[333,333,"A"],[334,337,"N"],[338,339,"A"],[340,357,"N"],[358,359,"A"],[360,362,"N"],[363,363,"A"],[364,461,"N"],[462,462,"A"],[463,463,"N"],[464,464,"A"],[465,465,"N"],[466,466,"A"],[467,467,"N"],[468,468,"A"],[469,469,"N"],[470,470,"A"],[471,471,"N"],[472,472,"A"],[473,473,"N"],[474,474,"A"],[475,475,"N"],[476,476,"A"],[477,592,"N"],[593,593,"A"],[594,608,"N"],[609,609,"A"],[610,707,"N"],[708,708,"A"],[709,710,"N"],[711,711,"A"],[712,712,"N"],[713,715,"A"],[716,716,"N"],[717,717,"A"],[718,719,"N"],[720,720,"A"],[721,727,"N"],[728,731,"A"],[732,732,"N"],[733,733,"A"],[734,734,"N"],[735,735,"A"],[736,767,"N"],[768,879,"A"],[880,912,"N"],[913,929,"A"],[930,930,"N"],[931,937,"A"],[938,944,"N"],[945,961,"A"],[962,962,"N"],[963,969,"A"],[970,1024,"N"],[1025,1025,"A"],[1026,1039,"N"],[1040,1103,"A"],[1104,1104,"N"],[1105,1105,"A"],[1106,4351,"N"],[4352,4447,"W"],[4448,8207,"N"],[8208,8208,"A"],[8209,8210,"N"],[8211,8214,"A"],[8215,8215,"N"],[8216,8217,"A"],[8218,8219,"N"],[8220,8221,"A"],[8222,8223,"N"],[8224,8226,"A"],[8227,8227,"N"],[8228,8231,"A"],[8232,8239,"N"],[8240,8240,"A"],[8241,8241,"N"],[8242,8243,"A"],[8244,8244,"N"],[8245,8245,"A"],[8246,8250,"N"],[8251,8251,"A"],[8252,8253,"N"],[8254,8254,"A"],[8255,8307,"N"],[8308,8308,"A"],[8309,8318,"N"],[8319,8319,"A"],[8320,8320,"N"],[8321,8324,"A"],[8325,8360,"N"],[8361,8361,"H"],[8362,8363,"N"],[8364,8364,"A"],[8365,8450,"N"],[8451,8451,"A"],[8452,8452,"N"],[8453,8453,"A"],[8454,8456,"N"],[8457,8457,"A"],[8458,8466,"N"],[8467,8467,"A"],[8468,8469,"N"],[8470,8470,"A"],[8471,8480,"N"],[8481,8482,"A"],[8483,8485,"N"],[8486,8486,"A"],[8487,8490,"N"],[8491,8491,"A"],[8492,8530,"N"],[8531,8532,"A"],[8533,8538,"N"],[8539,8542,"A"],[8543,8543,"N"],[8544,8555,"A"],[8556,8559,"N"],[8560,8569,"A"],[8570,8584,"N"],[8585,8585,"A"],[8586,8591,"N"],[8592,8601,"A"],[8602,8631,"N"],[8632,8633,"A"],[8634,8657,"N"],[8658,8658,"A"],[8659,8659,"N"],[8660,8660,"A"],[8661,8678,"N"],[8679,8679,"A"],[8680,8703,"N"],[8704,8704,"A"],[8705,8705,"N"],[8706,8707,"A"],[8708,8710,"N"],[8711,8712,"A"],[8713,8714,"N"],[8715,8715,"A"],[8716,8718,"N"],[8719,8719,"A"],[8720,8720,"N"],[8721,8721,"A"],[8722,8724,"N"],[8725,8725,"A"],[8726,8729,"N"],[8730,8730,"A"],[8731,8732,"N"],[8733,8736,"A"],[8737,8738,"N"],[8739,8739,"A"],[8740,8740,"N"],[8741,8741,"A"],[8742,8742,"N"],[8743,8748,"A"],[8749,8749,"N"],[8750,8750,"A"],[8751,8755,"N"],[8756,8759,"A"],[8760,8763,"N"],[8764,8765,"A"],[8766,8775,"N"],[8776,8776,"A"],[8777,8779,"N"],[8780,8780,"A"],[8781,8785,"N"],[8786,8786,"A"],[8787,8799,"N"],[8800,8801,"A"],[8802,8803,"N"],[8804,8807,"A"],[8808,8809,"N"],[8810,8811,"A"],[8812,8813,"N"],[8814,8815,"A"],[8816,8833,"N"],[8834,8835,"A"],[8836,8837,"N"],[8838,8839,"A"],[8840,8852,"N"],[8853,8853,"A"],[8854,8856,"N"],[8857,8857,"A"],[8858,8868,"N"],[8869,8869,"A"],[8870,8894,"N"],[8895,8895,"A"],[8896,8977,"N"],[8978,8978,"A"],[8979,8985,"N"],[8986,8987,"W"],[8988,9e3,"N"],[9001,9002,"W"],[9003,9192,"N"],[9193,9196,"W"],[9197,9199,"N"],[9200,9200,"W"],[9201,9202,"N"],[9203,9203,"W"],[9204,9311,"N"],[9312,9449,"A"],[9450,9450,"N"],[9451,9547,"A"],[9548,9551,"N"],[9552,9587,"A"],[9588,9599,"N"],[9600,9615,"A"],[9616,9617,"N"],[9618,9621,"A"],[9622,9631,"N"],[9632,9633,"A"],[9634,9634,"N"],[9635,9641,"A"],[9642,9649,"N"],[9650,9651,"A"],[9652,9653,"N"],[9654,9655,"A"],[9656,9659,"N"],[9660,9661,"A"],[9662,9663,"N"],[9664,9665,"A"],[9666,9669,"N"],[9670,9672,"A"],[9673,9674,"N"],[9675,9675,"A"],[9676,9677,"N"],[9678,9681,"A"],[9682,9697,"N"],[9698,9701,"A"],[9702,9710,"N"],[9711,9711,"A"],[9712,9724,"N"],[9725,9726,"W"],[9727,9732,"N"],[9733,9734,"A"],[9735,9736,"N"],[9737,9737,"A"],[9738,9741,"N"],[9742,9743,"A"],[9744,9747,"N"],[9748,9749,"W"],[9750,9755,"N"],[9756,9756,"A"],[9757,9757,"N"],[9758,9758,"A"],[9759,9775,"N"],[9776,9783,"W"],[9784,9791,"N"],[9792,9792,"A"],[9793,9793,"N"],[9794,9794,"A"],[9795,9799,"N"],[9800,9811,"W"],[9812,9823,"N"],[9824,9825,"A"],[9826,9826,"N"],[9827,9829,"A" Line truncated
`);for(;e[0].indexOf("|")===-1;)e.shift();for(let i=0,r=e.length;i<r;i++){if(e[i].indexOf("|")===-1)continue;e[i]=this.trimStartOfLineContent(e[i]),this.cells[i]=[];let s=e[i].split("|");for(let a=0,o=s.length;a<o;a++)this.cells[i][a]=s[a].trim(),i===1&&(this.cells[i][a]=this.cells[i][a].replace(/-+/g,"-"))}if(this.getColumnWidths(),this.columnWidths[0]===0)for(let i=0,r=this.cells.length;i<r;i++)this.cells[i].shift();if(this.getColumnWidths(),this.columnWidths[this.columnWidths.length-1]===0)for(let i=0,r=this.cells.length;i<r;i++)this.cells[i].length===this.columnWidths.length&&this.cells[i].pop();this.getColumnWidths()}addMissingCellColumns(){for(let t=0,e=this.cells.length;t<e;t++)for(let i=0,r=this.columnWidths.length;i<r;i++)typeof this.cells[t][i]>"u"&&(this.cells[t][i]="")}trimStartOfLineContent(t){if(!this.startOfLine)return t;if(this.startOfLine.trim()==="")return t.startsWith(this.startOfLine)?t.slice(this.startOfLine.length):t;let e=Tt(this.startOfLine,">"),i=0,r=0;for(;r<t.length;){let s=t.charAt(r);if(s===">")i++;else{if(s==="|")break;if(s.trim()!=="")throw new Error(A("logs.unexpected-pre-table-content").replace("{TABLE_ROW}",t).replace("{START_OF_LINE}",this.startOfLine))}if(i>e)break;r++}return t.substring(r)}padCellsForOutput(){for(let t=0,e=this.cells.length;t<e;t++){let i=t!==1?" ":"-";for(let r=0,s=this.cells[t].length;r<s;r++){let a=eb(this.cells[t][r]);a<this.columnWidths[r]&&(this.cells[t][r]+=i.repeat(this.columnWidths[r]-a))}}}formatTable(t,e){this.startOfLine=e,this.importTable(t),this.getColumnWidths(),this.addMissingCellColumns(),this.padCellsForOutput(),this.outputTable="| ",this.outputTable+=this.cells[0].join(" | "),this.outputTable+=` |
`,this.outputTable+=e,this.outputTable+="|-",this.outputTable+=this.cells[1].join("-|-"),this.outputTable+=`-|
`;for(let i=2,r=this.cells.length;i<r;i++)this.outputTable+=e,this.outputTable+="| ",this.outputTable+=this.cells[i].join(" | "),this.outputTable+=` |
`;return this.outputTable=this.outputTable.replace(/\n+$/,""),this.outputTable}};var tm=class{},tb,em,rS;tb=[w.register];var ys=class extends(rS=w){constructor(){super({nameKey:"rules.align-table-columns.name",descriptionKey:"rules.align-table-columns.description",type:"Spacing",ruleIgnoreTypes:[y.yaml,y.code,y.math,y.inlineMath,y.wikiLink,y.link]})}get OptionsClass(){return tm}apply(t,e,i){let r=i.projection(),s=fi(r.text),a,o;if(s.length===0)return t;let l=r.text;for(let u of s){let d=l.substring(u.startIndex,u.endIndex),m=l.substring(pi(l,u.startIndex),u.startIndex);o=new Sc,a=o.formatTable(d,m),l=l.replace(d,a)}let c=[];for(let u of Ue(r.text,l)){let d=r.editRangeToSource(u);d&&c.push({...d,value:u.value})}return J(t,c)}get optionBuilders(){return[]}};em=I(rS),ys=O(em,0,"AlignTable",tb,ys),L(em,1,ys);function Nt(n){return n!==n.trim()?[!1,A("validation.yaml-key-no-whitespace").replace("{KEY}",n)]:n.includes(":")?[!1,A("validation.yaml-key-no-colon").replace("{KEY}",n)]:ib(n,n)}function nb(n){let t=n.trim();return t.endsWith(":")&&(t=t.slice(0,-1)),t.includes(":")?[!1,A("validation.yaml-key-only").replace("{KEY}",n)]:ib(t,n)}function ib(n,t){try{kn(n)}catch(e){let i;return e instanceof tt?(i=e.toString(),i=i.substring(i.indexOf(":")+1)):i=e.message,[!1,A("validation.yaml-key-only").replace("{KEY}",t).replace("{ERROR_MESSAGE}",i)]}return[!0,""]}function rb(n){try{dt(`${n}
test-valid-linter-yaml-key-value-test: true`)}catch{return[!1,A("validation.invalid-yaml").replace("{YAML",n)]}return[!0,""]}function Ec(n){return n.startsWith("#")?[!1,A("validation.no-hashtag-in-tag").replace("{TAG}",n)]:n.match(Tg)?[!0,""]:[!1,A("validation.invalid-tag").replace("{TAG}",n)]}function wo(n){return/\s/.test(n)?[!1,A("validation.no-whitespace").replace("{TEXT}",n)]:[!0,""]}var sb,Tc;sb=[w.noSettingControl()];var Ni=class{constructor(){this.ignoreWords=[];this.extraAutoCorrectFiles=[];this.skipWordsWithMultipleCapitals=!1;this.misspellingToCorrection=L(Tc,8,this,new Map),L(Tc,11,this)}};Tc=I(null),O(Tc,5,"misspellingToCorrection",sb,Ni),oe(Tc,Ni);var ab,nm,aS;ab=[w.register];var Ri=class extends(aS=w){constructor(){super({nameKey:"rules.auto-correct-common-misspellings.name",descriptionKey:"rules.auto-correct-common-misspellings.description",type:"Content",hasSpecialExecutionOrder:!0,ruleIgnoreTypes:[y.yaml,y.code,y.inlineCode,y.math,y.inlineMath,y.link,y.wikiLink,y.tag,y.image,y.url]})}get OptionsClass(){return Ni}apply(t,e,i){let r=i.projection(),s=[];for(let a of r.text.matchAll(Ig)){let o=r.editRangeToSource({startIndex:a.index,endIndex:a.index+a[0].length});if(o){let l=this.replaceWordWithCorrectCasing(a[0],e);l!==a[0]&&s.push({...o,value:l})}}return J(t,s)}replaceWordWithCorrectCasing(t,e){let i=t.toLowerCase();if(e.ignoreWords.includes(i)||e.skipWordsWithMultipleCapitals&&t.length>1&&i.substring(1)!==t.substring(1))return t;if(e.misspellingToCorrection.has(i))return this.determineCorrectedWord(t,e.misspellingToCorrection.get(i));if(e.extraAutoCorrectFiles){for(let r=0;r<e.extraAutoCorrectFiles.length;r++)if(e.extraAutoCorrectFiles[r].customReplacements instanceof Map&&e.extraAutoCorrectFiles[r].customReplacements?.has(i))return this.determineCorrectedWord(t,e.extraAutoCorrectFiles[r].customReplacements.get(i))}return t}determineCorrectedWord(t,e){return t.charAt(0)==t.charAt(0).toUpperCase()&&(e=e.charAt(0).toUpperCase()+e.substring(1)),e}get optionBuilders(){return[new Ae({OptionsClass:Ni,nameKey:"rules.auto-correct-common-misspellings.ignore-words.name",descriptionKey:"rules.auto-correct-common-misspellings.ignore-words.description",emptyStateKey:"rules.auto-correct-common-misspellings.ignore-words.empty-state",fieldNamePlaceholderKey:"rules.auto-correct-common-misspellings.ignore-words.placeholder-text",optionsKey:"ignoreWords",validator:wo}),new V({OptionsClass:Ni,nameKey:"rules.auto-correct-common-misspellings.skip-words-with-multiple-capitals.name",descriptionKey:"rules.auto-correct-common-misspellings.skip-words-with-multiple-capitals.description",optionsKey:"skipWordsWithMultipleCapitals"}),new Lc({OptionsClass:Ni,nameKey:"rules.auto-correct-common-misspellings.extra-auto-correct-files.name",descriptionKey:"rules.auto-correct-common-misspellings.extra-auto-correct-files.description",optionsKey:"extraAutoCorrectFiles"})]}};nm=I(aS),Ri=O(nm,0,"AutoCorrectCommonMisspellings",ab,Ri),L(nm,1,Ri);var Mc=class{constructor(){this.style="space"}},ob,im,lS;ob=[w.register];var Fi=class extends(lS=w){constructor(){super({nameKey:"rules.blockquote-style.name",descriptionKey:"rules.blockquote-style.description",type:"Content",hasSpecialExecutionOrder:!0,ruleIgnoreTypes:[y.html,y.code,y.math]})}get OptionsClass(){return Mc}apply(t,e,i){let r=on.for(t).protectedRangesFor([y.code,y.math]);return fg(t,(s,a)=>{let o=[],l=[],c=[],u=0,d=!1;do{let m=s.indexOf(`
`,u);m===-1&&(m=s.length-1,d=!0);let[p,h]=ur(s,m-1),f=a+h+1,g=f+p.length,b=a+m+(d?1:0);o.push(r.isProtected(f,b)||i.isProtected(f,g));let k=Hn(t,i,g,b);l.push(ul.test(k)),c.push(k.trim()!==""),u=m+1}while(!d);return m=>this.updateBlockquoteLines(m,e.style==="space"?this.addSpaceToIndicator:this.removeSpaceFromIndicator,o,l,c)})}removeSpaceFromIndicator(t,e){return e?t.replace(/>[ \t]+>/g,">>"):t.replace(/>[ \t]+/g,">")}addSpaceToIndicator(t,e,i=!0){if(!i)return t.replace(/>([^ >])/g,"> $1").replace(/>>/g,"> >").replace(/[ \t]+$/,"");let r=t.replace(/>([^ ]|$)/g,"> $1").replace(/>>/g,"> >");return e?r:r.replace(/>(?:[ \t]{2,}|\t+)/g,"> ")}updateBlockquoteLines(t,e,i,r,s){let a=0,o,l,c,u,d=t,m=!1,p=0;do{o=d.indexOf(`
`,a),o===-1&&(o=d.length-1,m=!0),[l,u]=ur(d,o-1);let h=p++;if(i[h]){a=o+1;continue}c=e(l,r[h],s[h]),u++,d=ui(d,u,u+l.length,c),a=o+1+c.length-l.length}while(!m);return d}get optionBuilders(){return[new de({OptionsClass:Mc,nameKey:"rules.blockquote-style.style.name",descriptionKey:"rules.blockquote-style.style.description",optionsKey:"style",records:[{value:"space",description:"> indicator is followed by a space"},{value:"no space",description:">indicator is not followed by a space"}]})]}};im=I(lS),Fi=O(im,0,"BlockquoteStyle",ob,Fi),L(im,1,Fi);var lb,Oc;lb=[w.noSettingControl()];var xo=class{constructor(){this.lineContent=L(Oc,8,this),L(Oc,11,this)}};Oc=I(null),O(Oc,5,"lineContent",lb,xo),oe(Oc,xo);var cb,rm,dS;cb=[w.register];var Bi=class extends(dS=w){constructor(){super({nameKey:"rules.add-blockquote-indentation-on-paste.name",descriptionKey:"rules.add-blockquote-indentation-on-paste.description",type:"Paste"})}get OptionsClass(){return xo}apply(t,e){let i=/^(\s*)((> ?)+) .*/,r=e.lineContent.match(i);if(!r)return t;let s=r[1]??"",a=r[2]??"";return t.trim().replace(/\n/gm,`
${s}${a} `)}get optionBuilders(){return[]}};rm=I(dS),Bi=O(rm,0,"BlockquotifyOnPaste",cb,Bi),L(rm,1,Bi);var ni=class{constructor(){this.style="Title Case";this.ignoreWords=["macOS","iOS","iPhone","iPad","JavaScript","TypeScript","AppleScript","I"];this.lowercaseWords=["a","an","the","aboard","about","abt.","above","abreast","absent","across","after","against","along","aloft","alongside","amid","amidst","mid","midst","among","amongst","anti","apropos","around","round","as","aslant","astride","at","atop","ontop","bar","barring","before","B4","behind","below","beneath","neath","beside","besides","between","'tween","beyond","but","by","chez","circa","c.","ca.","come","concerning","contra","counting","cum","despite","spite","down","during","effective","ere","except","excepting","excluding","failing","following","for","from","in","including","inside","into","less","like","minus","modulo","mod","near","nearer","nearest","next","notwithstanding","of","o'","off","offshore","on","onto","opposite","out","outside","over","o'er","pace","past","pending","per","plus","post","pre","pro","qua","re","regarding","respecting","sans","save","saving","short","since","sub","than","through","thru","throughout","thruout","till","times","to","t'","touching","toward","towards","under","underneath","unlike","until","unto","up","upon","versus","vs.","v.","via","vice","vis-\xE0-vis","wanting","with","w/","w.","c\u0304","within","w/i","without","'thout","w/o","abroad","adrift","aft","afterward","afterwards","ahead","apart","ashore","aside","away","back","backward","backwards","beforehand","downhill","downstage","downstairs","downstream","downward","downwards","downwind","east","eastward","eastwards","forth","forward","forwards","heavenward","heavenwards","hence","henceforth","here","hereby","herein","hereof","hereto","herewith","home","homeward","homewards","indoors","inward","inwards","leftward","leftwards","north","northeast","northward","northwards","northwest","now","onward","onwards","outdoors","outward","outwards","overboard","overhead","overland","overseas","rightward","rightwards","seaward","seawards","skywards","skyward","south","southeast","southwards","southward","southwest","then","thence","thenceforth","there","thereby","therein","thereof","thereto","therewith","together","underfoot","underground","uphill","upstage","upstairs","upstream","upward","upwards","upwind","west","westward","westwards","when","whence","where","whereby","wherein","whereto","wherewith","although","because","considering","given","granted","if","lest","once","provided","providing","seeing","so","supposing","though","unless","whenever","whereas","wherever","while","whilst","ago","inasmuch","even","whether","whose","whoever","why","how","whatever","what","both","and","or","either","neither","nor","just","rather","such","that","yet","is","it"];this.startingWordIgnoreCharacters=`'"(\u2018\u201C-`;this.endingWordIgnoreCharacters=`.?!,:;'")\u201D\u20190123456789-`;this.ignoreCasedWords=!0}},db,sm,mS;db=[w.register];var Di=class extends(mS=w){constructor(){super({nameKey:"rules.capitalize-headings.name",descriptionKey:"rules.capitalize-headings.description",type:"Heading",hasSpecialExecutionOrder:!0,ruleIgnoreTypes:[y.code,y.inlineCode,y.yaml,y.link,y.wikiLink,y.tag]})}get OptionsClass(){return ni}apply(t,e,i){let r=i.projection(),s=[];for(let a of r.text.matchAll(cn)){if(!a[4]||a[4].trim()=="")continue;let o=(d,m,p)=>{let h=r.editRangeToSource({startIndex:a.index+d,endIndex:a.index+m});h&&t.substring(h.startIndex,h.endIndex)!==p&&s.push({...h,value:p})};if(e.style==="ALL CAPS"){let d=0;for(let m of a[0])o(d,d+m.length,m.toUpperCase()),d+=m.length;continue}let l=[...a[0].matchAll(fu)],c=this.capitalizeHeading(a[0],e).split(" "),u=0;for(let d=0;d<l.length;d++){let m=l[d];o(u,m.index,d===0?"":" "),o(m.index,m.index+m[0].length,c[d]),u=m.index+m[0].length}o(u,a[0].length,"")}return J(t,s)}capitalizeHeading(t,e){return t.replace(cn,i=>{if(e.style==="ALL CAPS")return i.toUpperCase();let r=e.style==="First letter",s=i.match(fu);if(!s)return i;let a=e.startingWordIgnoreCharacters?.length==0?"":`[${Mt(e.startingWordIgnoreCharacters)}]?`,o=e.endingWordIgnoreCharacters?.length==0?"":`[${Mt(e.endingWordIgnoreCharacters)}]*`,l=new RegExp(`^${a}[\\p{L}\u2019'-]{1,}${o}$`,"u"),c=e.ignoreWords,u=e.lowercaseWords,d=!0;for(let m=1;m<s.length;m++){if(!s[m].match(l)||s[m]==="-"||s[m]==="'")continue;let h=0;if(e.startingWordIgnoreCharacters?.includes(s[m][0])&&(h=1),e.ignoreCasedWords&&s[m]!==s[m].toLowerCase()||c.includes(s[m])||(s[m]=s[m].toLowerCase(),(!u.includes(s[m])&&!r||d===!0)&&(h===0?s[m]=s[m][h].toUpperCase()+s[m].slice(h+1):s[m]=s[m][0]+s[m][h].toUpperCase()+s[m].slice(h+1))),d=!1,e.ignoreCasedWords&&r)break}return s.join(" ")})}get optionBuilders(){return[new de({OptionsClass:ni,nameKey:"rules.capitalize-headings.style.name",descriptionKey:"rules.capitalize-headings.style.description",optionsKey:"style",records:[{value:"Title Case",description:"Capitalize Using TitleLine truncated
`),i=i.replace(/\n+---/,`
---`),e.innerNewLines&&(i=_y(i)),i))}get optionBuilders(){return[new V({OptionsClass:Cc,nameKey:"rules.compact-yaml.inner-new-lines.name",descriptionKey:"rules.compact-yaml.inner-new-lines.description",optionsKey:"innerNewLines"})]}};am=I(fS),bs=O(am,0,"CompactYaml",ub,bs),L(am,1,bs);var lm=class{},mb,om,gS;mb=[w.register];var Yi=class extends(gS=w){constructor(){super({nameKey:"rules.consecutive-blank-lines.name",descriptionKey:"rules.consecutive-blank-lines.description",type:"Spacing",ruleIgnoreTypes:[y.code,y.math,y.yaml,y.link,y.wikiLink,y.tag],hasSpecialExecutionOrder:!0})}get OptionsClass(){return lm}apply(t,e,i){let r=i.projection(),s=[];for(let a of r.text.matchAll(Zr)){let o=r.editRangeToSource({startIndex:a.index,endIndex:a.index+a[0].length});o&&s.push({...o,value:`
`})}return J(t,s)}get optionBuilders(){return[]}};om=I(gS),Yi=O(om,0,"ConsecutiveBlankLines",mb,Yi),L(om,1,Yi);var dm=class{},pb,cm,bS;pb=[w.register];var ks=class extends(bS=w){constructor(){super({nameKey:"rules.convert-bullet-list-markers.name",descriptionKey:"rules.convert-bullet-list-markers.description",type:"Content",ruleIgnoreTypes:[y.code,y.math,y.yaml,y.link,y.wikiLink,y.tag]})}get OptionsClass(){return dm}apply(t,e,i){let r=(s,a)=>({startIndex:a+s[1].length,endIndex:a+s[1].length+s[2].length,value:"-"});return ke(t,le(t,/^([^\S\n]*)([•§])([^\S\n]*)/gm,i,{editRange:r,guardRange:r}))}get optionBuilders(){return[]}};cm=I(bS),ks=O(cm,0,"ConvertBulletListMarkers",pb,ks),L(cm,1,ks);var Ic=class{constructor(){this.tabsize=4}},fb,um,vS;fb=[w.register];var vs=class extends(vS=w){constructor(){super({nameKey:"rules.convert-spaces-to-tabs.name",descriptionKey:"rules.convert-spaces-to-tabs.description",type:"Spacing",ruleIgnoreTypes:[y.code,y.math,y.yaml,y.link,y.wikiLink,y.tag]})}get OptionsClass(){return Ic}apply(t,e,i){let r=String(e.tabsize),s=new RegExp("^( *) {"+r+"}","gm");[t,i]=this.replaceAllRegexMatches(t,s,i);let a=new RegExp("^((>( | *))*(>( | )) *) {"+r+"}","gm");return[t]=this.replaceAllRegexMatches(t,a,i,!0),t}replaceAllRegexMatches(t,e,i,r=!1){let s=(a,o)=>({startIndex:o+a[1].length,endIndex:o+a[0].length,value:" "});for(;;){let a=le(t,e,i,{editRange:s,guardRange:r?(c,u)=>({startIndex:u,endIndex:u+c[0].length}):s});if(a.length===0)return[t,i];t=ke(t,a);let o=0,l=0;i=new Et(i.ranges.map(c=>{for(;o<a.length&&a[o].endIndex<=c.startIndex;){let u=a[o++];l+=u.value.length-(u.endIndex-u.startIndex)}return{startIndex:c.startIndex+l,endIndex:c.endIndex+l}}))}}get optionBuilders(){return[new wc({OptionsClass:Ic,nameKey:"rules.convert-spaces-to-tabs.tabsize.name",descriptionKey:"rules.convert-spaces-to-tabs.tabsize.description",optionsKey:"tabsize"})]}};um=I(vS),vs=O(um,0,"ConvertSpacesToTabs",fb,vs),L(um,1,vs);var hb,gb,yb,bb,Ft;bb=[w.noSettingControl()],yb=[w.noSettingControl()],gb=[w.noSettingControl()],hb=[w.noSettingControl()];var Gt=class{constructor(){this.aliasArrayStyle=L(Ft,8,this,"single-line"),L(Ft,11,this);this.dedupeAliasKey=!0;this.tagArrayStyle=L(Ft,12,this,"single-line"),L(Ft,15,this);this.dedupeTagKey=!0;this.dedupeArrayKeys=!0;this.ignoreDedupeArrayKeys=[];this.defaultEscapeCharacter=L(Ft,16,this,'"'),L(Ft,19,this);this.removeUnnecessaryEscapeCharsForMultiLineArrays=L(Ft,20,this,!1),L(Ft,23,this)}};Ft=I(null),O(Ft,5,"aliasArrayStyle",bb,Gt),O(Ft,5,"tagArrayStyle",yb,Gt),O(Ft,5,"defaultEscapeCharacter",gb,Gt),O(Ft,5,"removeUnnecessaryEscapeCharsForMultiLineArrays",hb,Gt),oe(Ft,Gt);var kb,mm,wS;kb=[w.register];var As=class extends(wS=w){constructor(){super({nameKey:"rules.dedupe-yaml-array-values.name",descriptionKey:"rules.dedupe-yaml-array-values.description",type:"YAML"})}get OptionsClass(){return Gt}apply(t,e){return Ee(t,i=>{let r=dt(i.replace(`---
`,"").replace(`
---`,""));if(!r)return i;for(let s of It)if(e.dedupeAliasKey&&Object.keys(r).includes(s)){i=he(i,s,Se(wn(this.getUniqueArray(Ne(Le(i,s)))),e.aliasArrayStyle,e.defaultEscapeCharacter,e.removeUnnecessaryEscapeCharsForMultiLineArrays,!0));break}for(let s of Ct)if(e.dedupeTagKey&&Object.keys(r).includes(s)){i=he(i,s,Se(An(this.getUniqueArray(Ne(Le(i,s)))),e.tagArrayStyle,e.defaultEscapeCharacter,e.removeUnnecessaryEscapeCharsForMultiLineArrays));break}if(e.dedupeArrayKeys){let s=[...It,...Ct,...e.ignoreDedupeArrayKeys];for(let a of Object.keys(r)){if(s.includes(a)||!Array.isArray(r[a])||r[a].length!==0&&typeof r[a][0]=="object"&&r[a][0]!==null)continue;let o=Le(i,a),l="single-line";o.includes(`
`)&&(l="multi-line");let c=this.getUniqueArray(Ne(o));i=he(i,a,Se(c,l,e.defaultEscapeCharacter,e.removeUnnecessaryEscapeCharsForMultiLineArrays))}}return i})}getYamlValue(t){return typeof t!="string"||t.length<2?t:t.startsWith("'")&&t.endsWith("'")||t.startsWith('"')&&t.endsWith('"')?t.slice(1,-1):t}getUniqueArray(t){if(t==null||typeof t=="string"||t.length<=1)return t;let e=new Set,i=[];for(let r of t){let s=this.getYamlValue(r);e.has(s)||(e.add(s),i.push(r))}return i}get optionBuilders(){return[new V({OptionsClass:Gt,nameKey:"rules.dedupe-yaml-array-values.dedupe-alias-key.name",descriptionKey:"rules.dedupe-yaml-array-values.dedupe-alias-key.description",optionsKey:"dedupeAliasKey"}),new V({OptionsClass:Gt,nameKey:"rules.dedupe-yaml-array-values.dedupe-tag-key.name",descriptionKey:"rules.dedupe-yaml-array-values.dedupe-tag-key.description",optionsKey:"dedupeTagKey"}),new V({OptionsClass:Gt,nameKey:"rules.dedupe-yaml-array-values.dedupe-array-keys.name",descriptionKey:"rules.dedupe-yaml-array-values.dedupe-array-keys.description",optionsKey:"dedupeArrayKeys"}),new Ae({OptionsClass:Gt,nameKey:"rules.dedupe-yaml-array-values.ignore-keys.name",descriptionKey:"rules.dedupe-yaml-array-values.ignore-keys.description",emptyStateKey:"rules.dedupe-yaml-array-values.ignore-keys.empty-state",fieldNamePlaceholderKey:"rules.dedupe-yaml-array-values.ignore-keys.placeholder-text",optionsKey:"ignoreDedupeArrayKeys",trimItemWhitespace:!0,validator:Nt})]}};mm=I(wS),As=O(mm,0,"DedupeYamlArrayValues",kb,As),L(mm,1,As);var Rc=class{constructor(){this.defaultLanguage=""}},vb,pm,LS;vb=[w.register];var ws=class extends(LS=w){constructor(){super({nameKey:"rules.default-language-for-code-fences.name",descriptionKey:"rules.default-language-for-code-fences.description",type:"Content",ruleIgnoreTypes:[y.yaml,y.math,y.link,y.wikiLink,y.tag]})}get OptionsClass(){return Rc}apply(t,e,i){return yg(t,e.defaultLanguage,i)}get optionBuilders(){return[new Te({OptionsClass:Rc,nameKey:"rules.default-language-for-code-fences.default-language.name",descriptionKey:"rules.default-language-for-code-fences.default-language.description",optionsKey:"defaultLanguage"})]}};pm=I(LS),ws=O(pm,0,"DefaultLanguageForCodeFences",vb,ws),L(pm,1,ws);var Nc=class{constructor(){this.style="consistent"}},Ab,fm,ES;Ab=[w.register];var xs=class extends(ES=w){constructor(){super({nameKey:"rules.emphasis-style.name",descriptionKey:"rules.emphasis-style.description",type:"Content",ruleIgnoreTypes:[y.code,y.math,y.yaml,y.link,y.wikiLink,y.tag,y.inlineMath]})}get OptionsClass(){return Nc}apply(t,e,i){return dl(t,e.style,"emphasis",i)}get optionBuilders(){return[new de({OptionsClass:Nc,nameKey:"rules.emphasis-style.style.name",descriptionKey:"rules.emphasis-style.style.description",optionsKey:"style",records:[{value:"consistent",description:"Makes sure the first instance of emphasis is the style that will be used throughout the document"},{value:"asterisk",description:"Makes sure * is the emphasis indicator"},{value:"underscore",description:"Makes sure _ is the emphasis indicator"}]})]}};fm=I(ES),xs=O(fm,0,"EmphasisStyle",Ab,xs),L(fm,1,xs);var gm=class{},wb,hm,MS;wb=[w.register];var Ls=class extends(MS=w){constructor(){super({nameKey:"rules.empty-line-around-blockquotes.name",descriptionKey:"rules.empty-line-around-blockquotes.description",type:"Spacing"})}get OptionsClass(){return gm}apply(t,e,i){return dg(t,i)}get optionBuilders(){return[]}};hm=I(MS),Ls=O(hm,0,"EmptyLineAroundBlockquotes",wb,Ls),L(hm,1,Ls);var bm=class{},xb,ym,CS;xb=[w.register];var Ss=class extends(CS=w){constructor(){super({nameKey:"rules.empty-line-around-code-fences.name",descriptionKey:"rules.empty-line-around-code-fences.description",type:"Spacing"})}get OptionsClass(){return bm}apply(t,e,i){return lg(t,i)}get optionBuilders(){return[]}};ym=I(CS),Ss=O(ym,0,"EmptyLineAroundCodeFences",xb,Ss),L(ym,1,Ss);var vm=class{},Lb,km,RS;Lb=[w.register];var Es=class extends(RS=w){constructor(){super({nameKey:"rules.empty-line-around-horizontal-rules.name",descriptionKey:"rules.empty-line-around-horizontal-rules.description",type:"Spacing"})}get OptionsClass(){return vm}apply(t,e,i){return ug(t,i)}get optionBuilders(){return[]}};km=I(RS),Es=O(km,0,"EmptyLineAroundHorizontalRules",Lb,Es),L(km,1,Es);var Sb,Fc;Sb=[w.noSettingControl()];var Lo=class{constructor(){this.minimumNumberOfDollarSignsToBeAMathBlock=L(Fc,8,this,2),L(Fc,11,this)}};Fc=I(null),O(Fc,5,"minimumNumberOfDollarSignsToBeAMathBlock",Sb,Lo),oe(Fc,Lo);var Eb,Am,FS;Eb=[w.register];var Ts=class extends(FS=w){constructor(){super({nameKey:"rules.empty-line-around-math-blocks.name",descriptionKey:"rules.empty-line-around-math-blocks.description",type:"Spacing",ruleIgnoreTypes:[y.yaml,y.code]})}get OptionsClass(){return Lo}apply(t,e,i){return cg(t,e.minimumNumberOfDollarSignsToBeAMathBlock,i)}get optionBuilders(){return[]}};Am=I(FS),Ts=O(Am,0,"EmptyLineAroundMathBlock",Eb,Ts),L(Am,1,Ts);var xm=class{},Tb,wm,DS;Tb=[w.register];var Ms=class extends(DS=w){construc Line truncated
`);if(r.length<1)return i;let s=null;for(let a=0;a<r.length;a++){let o=r[a],l=YS(o),c=o.trim();if(s!==null){if(c.length===0||l>s)continue;s=null}if(c.length===0)continue;let u=c.indexOf(":"),d=c.startsWith("-"),m=u<0||u+1>=c.length,p=d&&c.length<2;if(m&&p)continue;let h=1;if(!d)h+=u;else if(u!==-1&&a+1<r.length){let g=o.indexOf("-")+1,b=0,k=r[a+1];for(;b<k.length&&(k[b]===" "||k[b]===" ");)b++;g<=b&&(h+=u)}let f=c.substring(h).trim();if(_S(f)){s=l;continue}if(f.startsWith("[")){if(!e.tryToEscapeSingleLineArrays||f.length<3)continue;let g=f.substring(1,f.length-1).split(",");for(let b=0;b<g.length;b++){let k=g[b].trim();k.startsWith("[")&&(k=k.substring(1).trimStart()),k.endsWith("]")&&(k=k.substring(0,k.length-1).trimEnd()),g[b]=g[b].replace(k,nt(k,e.defaultEscapeCharacter,!1,!0))}r[a]=o.replace(f,`[${g.join(",")}]`);continue}r[a]=o.replace(f,nt(f,e.defaultEscapeCharacter,!1,!0))}return r.join(`
`)})}get optionBuilders(){return[new V({OptionsClass:Os,nameKey:"rules.escape-yaml-special-characters.try-to-escape-single-line-arrays.name",descriptionKey:"rules.escape-yaml-special-characters.try-to-escape-single-line-arrays.description",optionsKey:"tryToEscapeSingleLineArrays"})]}};Lm=I(PS),_i=O(Lm,0,"EscapeYamlSpecialCharacters",Ob,_i),L(Lm,1,_i);function YS(n){let t=0;for(;t<n.length&&(n[t]===" "||n[t]===" ");)t++;return t}function _S(n){return/^[|>](?:[1-9])?(?:[+-])?(?:[ \t]+#.*)?$/.test(n)}var Cb=require("obsidian");var Yn=class extends Cb.Modal{constructor(t,e,i,r,s){super(t),this.modalEl.addClass("confirm-modal"),this.contentEl.createEl("h3",{text:A("warning-text"),cls:"modal-heading"});let a=this.contentEl.createEl("p");a.id="confirm-dialog",zy(A("disabled-other-rule-notice").replace("{NAME_1}",A(e)).replace("{NAME_2}",A(i)),a),this.contentEl.createDiv("modal-button-container",o=>{o.createEl("button",{text:A("cancel-button-text")}).addEventListener("click",async()=>{await s(),this.close()});let l=o.createEl("button",{attr:{type:"submit"},cls:"mod-cta",text:A("ok")});l.addEventListener("click",async()=>{this.close(),await r()}),window.setTimeout(()=>{l.focus()},50)})}};var Ib,Dc;Ib=[w.noSettingControl()];var So=class{constructor(){this.fileName=L(Dc,8,this),L(Dc,11,this)}};Dc=I(null),O(Dc,5,"fileName",Ib,So),oe(Dc,So);var Rb,Sm,qS;Rb=[w.register];var Cs=class extends(qS=w){constructor(){super({nameKey:"rules.file-name-heading.name",descriptionKey:"rules.file-name-heading.description",type:"Heading",ruleIgnoreTypes:[y.code,y.math,y.yaml,y.link,y.wikiLink,y.tag],disableConflictingOptions(t,e,i){let r=Rt["header-increment"],s=r.options[0],a=r.options[1];t&&s.getValue(i)&&new Yn(e,"rules.file-name-heading.name","rules.header-increment.start-at-h2.name",async()=>{await a.setValue(!1,i),i.settingsTab.update()},async()=>{await Rt["file-name-heading"].options[0].setValue(!1,i),i.settingsTab.update()}).open()}})}get OptionsClass(){return So}apply(t,e,i){let r=i.projection(),s=r.text;if(s.match(/^#\s.*/m))return t;let o=e.fileName,l=s.indexOf(`
---`);l=l==-1||!s.startsWith(`---
`)?0:l+5;let c=`# ${eh(o)}
`;s.length<l&&(c=`
`+c);let u=Math.min(l,s.length),d=r.editRangeToSource({startIndex:u,endIndex:u}),m=d?[{...d,value:c}]:[];return J(t,m)}get optionBuilders(){return[]}};Sm=I(qS),Cs=O(Sm,0,"FileNameHeading",Rb,Cs),L(Sm,1,Cs);var Tm=class{},Nb,Em,jS;Nb=[w.register];var Is=class extends(jS=w){constructor(){super({nameKey:"rules.footnote-after-punctuation.name",descriptionKey:"rules.footnote-after-punctuation.description",type:"Footnote",ruleIgnoreTypes:[y.code,y.inlineCode,y.math,y.yaml,y.link,y.wikiLink,y.tag,y.footnoteAtStartOfLine,y.footnoteAfterATask]})}get OptionsClass(){return Tm}apply(t,e,i){let r=le(t,/(\[\^[^\]]+\]) ?([,.;!:?])/gm,i,{guardRange:(s,a)=>({startIndex:a,endIndex:a+s[0].length}),editRange:(s,a)=>({startIndex:a,endIndex:a+s[0].length,value:s[2]+s[1]})});return J(t,r)}get optionBuilders(){return[]}};Em=I(jS),Is=O(Em,0,"FootnoteAfterPunctuation",Nb,Is),L(Em,1,Is);var Fb,Yc;Fb=[w.noSettingControl()];var Rs=class{constructor(){this.defaultEscapeCharacter=L(Yc,8,this,'"'),L(Yc,11,this);this.forceYamlEscape=[]}};Yc=I(null),O(Yc,5,"defaultEscapeCharacter",Fb,Rs),oe(Yc,Rs);var Bb,Mm,HS;Bb=[w.register];var Ki=class extends(HS=w){constructor(){super({nameKey:"rules.force-yaml-escape.name",descriptionKey:"rules.force-yaml-escape.description",type:"YAML",hasSpecialExecutionOrder:!0})}get OptionsClass(){return Rs}apply(t,e){return Ee(t,i=>{for(let r of e.forceYamlEscape){let s=Le(i,r);if(s!=null){if(s.includes(`
`)||s.startsWith(" [")||Ei(s))continue;s=nt(s,e.defaultEscapeCharacter,!0),i=he(i,r," "+s)}}return i})}get optionBuilders(){return[new Ae({OptionsClass:Rs,nameKey:"rules.force-yaml-escape.force-yaml-escape-keys.name",descriptionKey:"rules.force-yaml-escape.force-yaml-escape-keys.description",emptyStateKey:"rules.force-yaml-escape.force-yaml-escape-keys.empty-state",fieldNamePlaceholderKey:"rules.force-yaml-escape.force-yaml-escape-keys.placeholder-text",optionsKey:"forceYamlEscape",validator:Nt})]}};Mm=I(HS),Ki=O(Mm,0,"ForceYamlEscape",Bb,Ki),L(Mm,1,Ki);var Cm=class{},Db,Om,VS;Db=[w.register];var Pi=class extends(VS=w){constructor(){super({nameKey:"rules.format-tags-in-yaml.name",descriptionKey:"rules.format-tags-in-yaml.description",type:"YAML",hasSpecialExecutionOrder:!0})}get OptionsClass(){return Cm}apply(t,e){return Ee(t,i=>i.replace(new RegExp(`^(${Bn}|${Wu}):[ \\t]*(\\S.*|(?:(?:\\n *- \\S.*)|((?:\\n *- *))*|(\\n([ \\t]+[^\\n]*))*)*)\\n`,"m"),function(r){return r.replaceAll("#","")}))}get optionBuilders(){return[]}};Om=I(VS),Pi=O(Om,0,"FormatTagsInYaml",Db,Pi),L(Om,1,Pi);var Yb,_b,Kb,Pb,zb,it;zb=[w.noSettingControl()],Pb=[w.noSettingControl()],Kb=[w.noSettingControl()],_b=[w.noSettingControl()],Yb=[w.noSettingControl()];var yt=class{constructor(){this.aliasArrayStyle=L(it,8,this,"single-line"),L(it,11,this);this.formatAliasKey=!0;this.tagArrayStyle=L(it,12,this,"single-line"),L(it,15,this);this.formatTagKey=!0;this.defaultArrayStyle=L(it,16,this,"single-line"),L(it,19,this);this.formatArrayKeys=!0;this.forceSingleLineArrayStyle=[];this.forceMultiLineArrayStyle=[];this.defaultEscapeCharacter=L(it,20,this,'"'),L(it,23,this);this.removeUnnecessaryEscapeCharsForMultiLineArrays=L(it,24,this,!1),L(it,27,this)}};it=I(null),O(it,5,"aliasArrayStyle",zb,yt),O(it,5,"tagArrayStyle",Pb,yt),O(it,5,"defaultArrayStyle",Kb,yt),O(it,5,"defaultEscapeCharacter",_b,yt),O(it,5,"removeUnnecessaryEscapeCharsForMultiLineArrays",Yb,yt),oe(it,yt);var qb,Im,QS;qb=[w.register];var Ns=class extends(QS=w){constructor(){super({nameKey:"rules.format-yaml-array.name",descriptionKey:"rules.format-yaml-array.description",type:"YAML"})}get OptionsClass(){return yt}apply(t,e){return Ee(t,i=>{let r=dt(i.replace(`---
`,"").replace(`
---`,""));if(!r)return i;for(let s of It)if(e.formatAliasKey&&Object.keys(r).includes(s)){i=he(i,s,Se(wn(Ne(Le(i,s))),e.aliasArrayStyle,e.defaultEscapeCharacter,e.removeUnnecessaryEscapeCharsForMultiLineArrays,!0));break}for(let s of Ct)if(e.formatTagKey&&Object.keys(r).includes(s)){i=he(i,s,Se(An(Ne(Le(i,s))),e.tagArrayStyle,e.defaultEscapeCharacter,e.removeUnnecessaryEscapeCharsForMultiLineArrays));break}if(e.formatArrayKeys){let s=[...It,...Ct,...e.forceMultiLineArrayStyle,...e.forceSingleLineArrayStyle];for(let a of Object.keys(r))s.includes(a)||!Array.isArray(r[a])||r[a].length!==0&&typeof r[a][0]=="object"&&r[a][0]!==null||(i=he(i,a,Se(Ne(Le(i,a)),e.defaultArrayStyle,e.defaultEscapeCharacter,e.removeUnnecessaryEscapeCharsForMultiLineArrays)))}for(let s of e.forceSingleLineArrayStyle)Object.keys(r).includes(s)&&(i=he(i,s,Se(Ne(Le(i,s)),"single-line",e.defaultEscapeCharacter,e.removeUnnecessaryEscapeCharsForMultiLineArrays)));for(let s of e.forceMultiLineArrayStyle)Object.keys(r).includes(s)&&(i=he(i,s,Se(Ne(Le(i,s)),"multi-line",e.defaultEscapeCharacter,e.removeUnnecessaryEscapeCharsForMultiLineArrays)));return i})}get optionBuilders(){return[new V({OptionsClass:yt,nameKey:"rules.format-yaml-array.alias-key.name",descriptionKey:"rules.format-yaml-array.alias-key.description",optionsKey:"formatAliasKey"}),new V({OptionsClass:yt,nameKey:"rules.format-yaml-array.tag-key.name",descriptionKey:"rules.format-yaml-array.tag-key.description",optionsKey:"formatTagKey"}),new V({OptionsClass:yt,nameKey:"rules.format-yaml-array.default-array-keys.name",descriptionKey:"rules.format-yaml-array.default-array-keys.description",optionsKey:"formatArrayKeys"}),new Ae({OptionsClass:yt,nameKey:"rules.format-yaml-array.force-single-line-array-style.name",descriptionKey:"rules.format-yaml-array.force-single-line-array-style.description",emptyStateKey:"rules.format-yaml-array.force-single-line-array-style.empty-state",fieldNamePlaceholderKey:"rules.format-yaml-array.force-single-line-array-style.placeholder-text",optionsKey:"forceSingleLineArrayStyle",validator:Nt}),new Ae({OptionsClass:yt,nameKey:"rules.format-yaml-array.force-multi-line-array-style.name",descriptionKey:"rules.format-yaml-array.force-multi-line-array-style.description",emptyStateKey:"rules.format-yaml-array.force-multi-line-array-style.empty-state",fieldNamePlaceholderKey:"rules.format-yaml-array.force-multi-line-array-style.placeholder-text",optionsKey:"forceMultiLineArrayStyle",validator:Nt})]}};Im=I(QS),Ns=O(Im,0,"FormatYamlArray",qb,Ns),L(Im,1,Ns);var _c=class{constructor(){this.startAtH2=!1}},Wb,Rm,ZS;Wb=[w.register];var Fs=class extends(ZS=w){constructor(){super({nameKey:"rules.header-increment.name",descriptionKey:"rules.header-increment.description",type:"Heading",ruleIgnoreTypes:[y.code,y.math,y.yaml,y.link,y.wikiLink,y.tag]})}get OptionsClass(){return _c}apply(t,e,i){let r=i.projection(),s=[],a=0,o=e.startAtH2?2:1,l=[],c=[0,0,0,0,0,0],u=c.length;for(let d of r.text.matchAll(cn)){let m=d.index+d[1].length,p=r.editRangeToSource({startIndex:m,endIndex:m+d[2].length});if(!p)continue;let h=d[2].length;if(h=h<=u?h:u,c[h-1]>=0&&h<a){let f=c.length;for(;l.length!==0&&h<=l[l.length-1];)f=l.pop();l.length===0?f=0:f--;for(let g=c.length-1;g>=f;g--)c[g]=0}if(c[h-1]<=0){let f=a,g=l.length+o;g=g<=u?g:u;for(let b=f;b<h-1;b++)c[b]=g-1;l.push(h),c[h-1]=g}a=h,s.push({...p,value:"#".repeat(c[h-1])})}return J(t,s)}get optionBuilders(){return[new V({OptionsClass:_c,nameKey:"rules.header-increment.start-at-h2.name",descriptionKey:"rules.header-increment.start-at-h2.description",optionsKey:"startAtH2",onChange(t,e,i){let r=Rt["file-name-heading"].options[0];t&&r.getValue(i)&&new Yn(e,"rules.header-increment.start-at-h2.name","rules.file-name-heading.name",async()=>{await r.setValue(!1,i)},async()=>{await Rt["header-increment"].options[1].setValue(!1,i)}).open()}})]}};Rm=I(ZS),Fs=O(Rm,0,"HeaderIncrement",Wb,Fs),L(Rm,1,Fs);var Eo=class{constructor(){this.bottom=!0;this.emptyLineAfterYaml=!0}},jb,Nm,e1;jb=[w.register];var Bs=class extends(e1=w){constructor(){super({nameKey:"rules.heading-blank-lines.name",descriptionKey:"rules.heading-blank-lines.description",type:"Spacing",ruleIgnoreTypes:[y.code,y.math,y.yaml,y.link,y.wikiLink]})}get OptionsClass(){return Eo}apply(t,e,i){let r=i.projection(),s=r.text;e.bottom?(s=s.replace(/^(#+\s.*)/gm,`
$1
`),s=s.replace(/\n+(#+\s.*)/g,`
$1`),s=s.replace(/(^#+\s.*)\n+/gm,`$1
`)):s=s.replace(/^([^#\n][^\n]+)\n+(#+\s.*)/gm,`$1
$2`),s=s.replace(/^\n+(#+\s.*)/,"$1"),s=s.replace(/(#+\s.*)\n+$/,"$1"),e.emptyLineAfterYaml||(s=s.replace(new RegExp("("+Ze.source+")\\n+(#+\\s.*)"),`$1
$5`));let a=[];for(let o of Ue(r.text,s)){let l=r.editRangeToSource(o);l&&a.push({...l,value:o.value})}return J(t,a)}get optionBuilders(){return[new V({OptionsClass:Eo,nameKey:"rules.heading-blank-lines.bottom.name",descriptionKey:"rules.heading-blank-lines.bottom.description",optionsKey:"bottom"}),new V({OptionsClass:Eo,nameKey:"rules.heading-blank-lines.empty-line-after-yaml.name",descriptionKey:"rules.heading-blank-lines.empty-line-after-yaml.description",optionsKey:"emptyLineAfterYaml"})]}};Nm=I(e1),Bs=O(Nm,0,"HeadingBlankLines",jb,Bs),L(Nm,1,Bs);var Bm=class{},Ub,Fm,n1;Ub=[w.register];var Ds=class extends(n1=w){constructor(){super({nameKey:"rules.headings-start-line.name",descriptionKey:"rules.headings-start-line.description",type:"Heading",ruleIgnoreTypes:[y.code,y.math,y.yaml]})}get OptionsClass(){return Bm}apply(t,e,i){let r=le(t,cn,i,{editRange:(s,a)=>({startIndex:a,endIndex:a+s[1].length,value:""}),guardRange:(s,a)=>({startIndex:a,endIndex:a+s[1].length+s[2].length+s[3].length})});return J(t,r)}get optionBuilders(){return[]}};Fm=I(n1),Ds=O(Fm,0,"HeadingStartLine",Ub,Ds),L(Fm,1,Ds);var Kc=class{constructor(){this.textToInsert=["aliases: ","tags: "]}},Hb,Dm,r1;Hb=[w.register];var Ys=class extends(r1=w){constructor(){super({nameKey:"rules.insert-yaml-attributes.name",descriptionKey:"rules.insert-yaml-attributes.description",type:"YAML"})}get OptionsClass(){return Kc}apply(t,e){return t=$t(t),Ee(t,i=>{let r=e.textToInsert.reverse(),s=dt(i.match(Ze)[1]);for(let a of r){let o=a.split(":"),l=o[0];o.length===1&&(a+=":"),Object.prototype.hasOwnProperty.call(s,l)||(i=i.replace(/^---\n/,ft(`---
${a}
`)))}return i})}get optionBuilders(){return[new Ae({OptionsClass:Kc,nameKey:"rules.insert-yaml-attributes.text-to-insert.name",descriptionKey:"rules.insert-yaml-attributes.text-to-insert.description",emptyStateKey:"rules.insert-yaml-attributes.text-to-insert.empty-state",fieldNamePlaceholderKey:"rules.insert-yaml-attributes.text-to-insert.placeholder-text",optionsKey:"textToInsert",validator:rb})]}};Dm=I(r1),Ys=O(Dm,0,"InsertYamlAttributes",Hb,Ys),L(Dm,1,Ys);var _m=class{},$b,Ym,a1;$b=[w.register];var _s=class extends(a1=w){constructor(){super({nameKey:"rules.line-break-at-document-end.name",descriptionKey:"rules.line-break-at-document-end.description",type:"Spacing"})}get OptionsClass(){return _m}apply(t,e){return t.length===0||(t=t.replace(/\n+$/g,""),t+=`
`),t}get optionBuilders(){return[]}};Ym=I(a1),_s=O(Ym,0,"LineBreakAtDocumentEnd",$b,_s),L(Ym,1,_s);var Pc=class{constructor(){this.includeBlankLineBetweenFootnotes=!1}},Vb,Km,l1;Vb=[w.register];var Ks=class extends(l1=w){constructor(){super({nameKey:"rules.move-footnotes-to-the-bottom.name",descriptionKey:"rules.move-footnotes-to-the-bottom.description",type:"Footnote",ruleIgnoreTypes:[y.code,y.inlineCode,y.math,y.yaml]})}get OptionsClass(){return Pc}apply(t,e,i){return eg(t,e.includeBlankLineBetweenFootnotes,i)}get optionBuilders(){return[new V({OptionsClass:Pc,nameKey:"rules.move-footnotes-to-the-bottom.include-blank-line-between-footnotes.name",descriptionKey:"rules.move-footnotes-to-the-bottom.include-blank-line-between-footnotes.description",optionsKey:"includeBlankLineBetweenFootnotes"})]}};Km=I(l1),Ks=O(Km,0,"MoveFootnotesToTheBottom",Vb,Ks),L(Km,1,Ks);var Qb,Jb,Zb,Xb,ek,rt;ek=[w.noSettingControl()],Xb=[w.noSettingControl()],Zb=[w.noSettingControl()],Jb=[w.noSettingControl()],Qb=[w.noSettingControl()];var Bt=class{constructor(){this.howToHandleFullLineFields="Move and remove";this.howToHandleBracketedFields="Leave in place";this.howToHandleExistingKeys="Skip";this.inlineKeysToIgnore=[];this.defaultEscapeCharacter=L(rt,8,this,'"'),L(rt,11,this);this.tagArrayStyle=L(rt,12,this,"single-line"),L(rt,15,this);this.aliasArrayStyle=L(rt,16,this,"single-line"),L(rt,19,this);this.defaultArrayStyle=L(rt,20,this,"single-line"),L(rt,23,this);this.removeUnnecessaryEscapeCharsForMultiLineArrays=L(rt,24,this,!1),L(rt,27,this)}};rt=I(null),O(rt,5,"defaultEscapeCharacter",ek,Bt),O(rt,5,"tagArrayStyle",Xb,Bt),O(rt,5,"aliasArrayStyle",Zb,Bt),O(rt,5,"defaultArrayStyle",Jb,Bt),O(rt,5,"removeUnnecessaryEscapeCharsForMultiLineArrays",Qb,Bt),oe(rt,Bt);var zc={"[":"]","(":")"},c1=/^[^0-9\w\p{Letter}]*((?:\p{Extended_Pictographic}|\u{200D}|\u{FE0F}|[0-9\p{Letter}\w\s/-])*)[_*~`]*$/u,d1=/^[\p{Letter}_][\p{Letter}\p{Number}_/-]*$/u,tk,zm,k1;tk=[w.register];var zi=class extends(k1=w){constructor(){super({nameKey:"rules.move-inline-fields-to-yaml.name",descriptionKey:"rules.move-inline-fields-to-yaml.description",type:"YAML",hasSpecialExecutionOrder:!0,ruleIgnoreTypes:[y.code,y.inlineCode,y.math,y.inlineMath,y.html,y.list,y.table,y.obsidianMultiLineComments]})}get OptionsClass(){return Bt}apply(t,e,i){let r=i.combinedWith([y.yaml]),s=this.getInlineFields(t,r,e);if(s.length===0)return t;let a=new Map;for(let h of s)a.has(h.key)||a.set(h.key,[]),a.get(h.key).push(h);let o=Mi(t)??"",l=[],c=[];for(let[h,f]of a){let g=u1(h),b=this.getNewValues(f.map(C=>C.value).filter(C=>C!==""),g,e);if(b==null)continue;let k=Le(o,h,!1),x=k==null?null:m1(k),E;if(k==null||e.howToHandleExistingKeys==="Overwrite")E=this.formatValues(b,x,g,e);else if(e.howToHandleExistingKeys==="Merge into list"){let C=this.getMergeableValues(k);if(C==null)continue;g===Bn?C=C.flatMap(F=>An(F)):g===Ti&&(C=C.flatMap(F=>wn(F)));let M=new Set(C.map(Pm)),N=[];for(let F of b)M.has(Pm(F))||(M.add(Pm(F)),N.push(F));if(c.push(...f),N.length===0)continue;E=this.formatValues([...C,...N],x,g,e),l.push({key:this.formatKey(h,e.defaultEscapeCharacter),value:E});continue}else continue;l.push({key:this.formatKey(h,e.defaultEscapeCharacter),value:E}),c.push(...f)}if(c.length===0)return t;let u=$t(t);u=Ee(u,h=>{h=h.replace(`---
`,"").replace("---","");for(let f of l)h=he(h,f.key,f.value,!1);return`---
${h}---`});let d=u.length-t.length,m=c.filter(h=>(h.isBracketed?e.howToHandleBracketedFields:e.howToHandleFullLineFields)!=="Move and keep in text"),p=this.getBodyEdits(t,m,e).map(h=>{let f=h.startIndex+d;return h.startIndex===0&&h.endIndex===t.length&&!t.endsWith(`
`)&&u.charAt(f-1)===`
`&&f--,{startIndex:f,endIndex:h.endIndex+d,value:h.value}});return J(u,p)}getInlineFields(t,e,i){let r=[],s=0;for(;s<=t.length;){let a=t.indexOf(`
`,s);a===-1&&(a=t.length);let o=t.substring(s,a);if(o.includes("::")){let l=g1(o);if(l.length>0){if(i.howToHandleBracketedFields!=="Leave in place")for(let c of l){let u=s+c.start,d=s+c.end;c.key===""||i.inlineKeysToIgnore.includes(c.key)||e.isProtected(u,d)||r.push({key:c.key,value:c.value,startIndex:u,endIndex:d,lineStartIndex:s,lineEndIndex:a,isBracketed:!0})}}else{let c=i.howToHandleFullLineFields==="Leave in place"?void 0:y1(o);c!=null&&c.key!==""&&!i.inlineKeysToIgnore.includes(c.key)&&!e.isProtected(s,a)&&r.push({key:c.key,value:c.value,startIndex:s,endIndex:a,lineStartIndex:s,lineEndIndex:a,isBracketed:!1})}}s=a+1}return r}getBodyEdits(t,e,i){let r=[],s=[],a=new Map;for(let c of e)a.has(c.lineStartIndex)||a.set(c.lineStartIndex,[]),a.get(c.lineStartIndex).push(c);for(let[c,u]of a){let d=u[0].lineEndIndex;if(!u[0].isBracketed){s.push({startIndex:c,endIndex:d});continue}let m=[],p=c;for(let f of u.sort((g,b)=>g.startIndex-b.startIndex)){if(i.howToHandleBracketedFields==="Move and keep value in text"&&f.value!==""){m.push({startIndex:f.startIndex,endIndex:f.endIndex,value:f.value}),p=f.endIndex;continue}let g=f.startIndex,b=f.endIndex,k=0;for(;g-k>p&&Gb(t.charAt(g-k-1));)k++;if(k>0||g===c)for(;b<d&&Gb(t.charAt(b));)b++;b===d&&(g-=k),m.push({startIndex:g,endIndex:b,value:""}),p=b}J(t.substring(c,d),m.map(f=>({startIndex:f.startIndex-c,endIndex:f.endIndex-c,value:f.value}))).trim()===""?s.push({startIndex:c,endIndex:d}):r.push(...m)}s.sort((c,u)=>c.startIndex-u.startIndex);let o=[];for(let c of s){let u=Math.min(c.endIndex+1,t.length),d=o[o.length-1];d&&d.endIndex===c.startIndex?d.endIndex=u:o.push({startIndex:c.startIndex,endIndex:u,value:""})}let l=o[o.length-1];return l&&l.endIndex===t.length&&l.startIndex>0&&!t.endsWith(`
`)&&l.startIndex--,[...r,...o]}escapeValue(t,e){let i=p1(t);if(i!=null){if(nk(t)===i)return t;t=i}try{let r=kn(t,{logLevel:"error"});if(typeof r=="string"&&r===t||typeof r=="number"||typeof r=="boolean")return t}catch{}return nt(t,e,!0)}formatKey(t,e){return d1.test(t)&&kn(t)===t?t:nt(t,e,!0)}getNewValues(t,e,i){if(e===Bn){let r=t.flatMap(s=>An(s)).map(s=>s.replace(/^#/,"")).filter(s=>s!=="");return r.some(s=>!Ec(s)[0])?null:r}else e===Ti&&(t=t.flatMap(r=>wn(r)));return t.map(r=>this.escapeValue(r,i.defaultEscapeCharacter))}formatValues(t,e,i,r){if(i===Bn)return Se(t,r.tagArrayStyle,r.defaultEscapeCharacter,r.removeUnnecessaryEscapeCharsForMultiLineArrays);if(i===Ti)return Se(t,r.aliasArrayStyle,r.defaultEscapeCharacter,r.removeUnnecessaryEscapeCharsForMultiLineArrays,!0);let s=r.defaultEscapeCharacter;if(e==null){if(t.length===0)return"";if(t.length===1)return" "+t[0];e=r.defaultArrayStyle}return Se(t,e,s,!1)}getMergeableValues(t){let e=t.trim();if(e==="")return[];if(/^[|>]/.test(e)||/(^|\s)#/.test(e))return null;let i;try{i=kn(t,{logLevel:"error"})}catch{return null}if(i!=null&&typeof i=="object"&&(!Array.isArray(i)||i.some(s=>s!=null&&typeof s=="object")))return null;let r=Ne(t);return r==null?[]:typeof r=="string"?[r]:r}get optionBuilders(){return[new de({OptionsClass:Bt,nameKey:"rules.move-inline-fields-to-yaml.how-to-handle-full-line-fields.name",descriptionKey:"rules.move-inline-fields-to-yaml.how-to-handle-full-line-fields.description",optionsKey:"howToHandleFullLineFields",records:[{value:"Leave in place",description:"Does not move full-line fields like `key:: value`"},{value:"Move and keep in text",description:"Adds full-line fields to the YAML frontmatter and leaves their lines as they are"},{value:"Move and remove",description:"Moves full-line fields to the YAML frontmatter and removes their lines"}]}),new de({OptionsClass:Bt,nameKey:"rules.move-inline-fields-to-yaml.how-to-handle-bracketed-fields.name",descriptionKey:"rules.move-inline-fields-to-yaml.how-to-handle-bracketed-fields.description",optionsKey:"howToHandleBracketedFields",records:[{value:"Leave in place",description:"Does not move bracketed fields like `[key:: value]` and `(key:: value)`"},{value:"Move and keep in text",description:"Adds bracketed fields to the YAML frontmatter and leaves them in the text as they are"},{value:"Move and keep value in text",description:"Moves bracketed fields to the YAML frontmatter and replaces them with their value"},{value:"Move and remove",description:"Moves bracketed fields to the YAML frontmatter and removes them from the body, removing the line if only whitespace is left"}]}),new de({OptionsClass:Bt,nameKey:"rules.move-inline-fields-to-yaml.how-to-handle-existing-keys.name",descriptionKey:"rules.move-inline-fields-to-yaml.how-to-handle-existing-keys.description",optionsKey:"howToHandleExistingKeys",records:[{value:"Skip",description:"Leaves the fields in the body and the YAML frontmatter value as is"},{value:"Merge into list",description:"Adds the field values to the YAML frontmatter value, turning it into a list"},{value:"Overwrite",description:"Replaces the YAML frontmatter value with the field values"}]}),new Ae({OptionsClass:Bt,nameKey:"rules.move-inline-fields-to-yaml.inline-keys-to-ignore.name",descriptionKey:"rules.move-inline-fields-to-yaml.inline-keys-to-ignore.description",emptyStateKey:"rules.move-inline-fields-to-yaml.inline-keys-to-ignore.empty-state",fieldNamePlaceholderKey:"rules.move-inline-fields-to-yaml.inline-keys-to-ignore.placeholder-text",optionsKey:"inlineKeysToIgnore",validator:Nt})]}};zm=I(k1),zi=O(zm,0,"MoveInlineFieldsToYaml",tk,zi),L(zm,1,zi);function u1(n){return Ct.includes(n)?Bn:It.includes(n)?Ti:null}function m1(n){let t=n.trim();return t.startsWith("[")?"single-line":t.startsWith("-")&&n.startsWith(`
`)?"multi-line":null}function nk(n){try{return kn(n,{logLevel:"error"})}catch{return}}function Pm(n){let t=nk(n);return typeof t=="string"||typeof t=="number"||typeof t=="boolean"?String(t):n}function p1(n){if(n.length<2||!n.startsWith('"')||!n.endsWith('"'))return null;let t="";for(let e=1;e<n.length-1;e++){let i=n.charAt(e);if(i==='"')return null;if(i==="\\"){if(e++,e>=n.length-1)return null;let r=n.charAt(e);t+=r==='"'||r==="\\"?r:"\\"+r}else t+=i}return t}function Gb(n){return n===" "||n===" "}function f1(n,t,e,i){let r=0,s=!1;for(let a=t;a<n.length;a++){let o=n.charAt(a);if(o==="\\"){s=!s;continue}if(s){s=!1;continue}if(o===e?r++:o===i&&r--,r<0)return{value:n.substring(t,a).trim(),endIndex:a+1}}}function h1(n,t){let e=n.charAt(t),i=n.indexOf("::",t+1);if(i===-1)return;let r=n.substring(t+1,i).trim();for(let a of[...Object.keys(zc),...Object.values(zc)])if(r.includes(a))return;let s=f1(n,i+2,e,zc[e]);if(s!==void 0)return{key:r,value:s.value,start:t,end:s.endIndex}}function g1(n){let t=[];for(let i of Object.keys(zc)){let r=n.indexOf(i);for(;r>=0;){let s=h1(n,r);if(!s){r=n.indexOf(i,r+1);continue}t.push(s),r=n.indexOf(i,s.end)}}t.sort((i,r)=>i.start-r.start);let e=[];for(let i of t)(e.length===0||e[e.length-1].end<i.start)&&e.push(i);return e}function y1(n){let t=n.indexOf("::");if(t===-1)return;let e=n.substring(0,t).trim().match(c1);if(e!=null)return{key:e[1].trim(),value:n.substring(t+2).trim()}}var ik,qc;ik=[w.noSettingControl()];var To=class{constructor(){this.minimumNumberOfDollarSignsToBeAMathBlock=L(qc,8,this,2),L(qc,11,this)}};qc=I(null),O(qc,5,"minimumNumberOfDollarSignsToBeAMathBlock",ik,To),oe(qc,To);var rk,qm,A1;rk=[w.register];var qi=class extends(A1=w){constructor(){super({nameKey:"rules.move-math-block-indicators-to-their-own-line.name",descriptionKey:"rules.move-math-block-indicators-to-their-own-line.description",type:"Spacing",ruleIgnoreTypes:[y.code,y.inlineCode],hasSpecialExecutionOrder:!0})}get OptionsClass(){return To}apply(t,e,i){return hg(t,e.minimumNumberOfDollarSignsToBeAMathBlock,i)}get optionBuilders(){return[]}};qm=I(A1),qi=O(qm,0,"MoveMathBlockIndicatorsToOwnLine",rk,qi),L(qm,1,qi);var sk,ak,ok,_n;ok=[w.noSettingControl()],ak=[w.noSettingControl()],sk=[w.noSettingControl()];var ii=class{constructor(){this.tagArrayStyle=L(_n,8,this,"single-line"),L(_n,11,this);this.howToHandleExistingTags="Nothing";this.tagsToIgnore=[];this.defaultEscapeCharacter=L(_n,12,this,'"'),L(_n,15,this);this.removeUnnecessaryEscapeCharsForMultiLineArrays=L(_n,16,this,!1),L(_n,19,this)}};_n=I(null),O(_n,5,"tagArrayStyle",ok,ii),O(_n,5,"defaultEscapeCharacter",ak,ii),O(_n,5,"removeUnnecessaryEscapeCharsForMultiLineArrays",sk,ii),oe(_n,ii);var lk,Wm,x1;lk=[w.register];var Ps=class extends(x1=w){constructor(){super({nameKey:"rules.move-tags-to-yaml.name",descriptionKey:"rules.move-tags-to-yaml.description",type:"YAML",ruleIgnoreTypes:[y.code,y.inlineCode,y.math,y.html,y.wikiLink,y.link]})}get OptionsClass(){return ii}apply(t,e,i){let r=i.projection(),s=i.combinedWith([y.yaml]).projection(),a=[...s.text.matchAll(fl)].filter(d=>s.editRangeToSource({startIndex:d.index,endIndex:d.index+d[0].length})!==void 0),o=a.map(d=>d[2]);if(o.length===0)return t;t=$t(r.text),t=Ee(t,d=>{d=d.replace(`---
`,"").replace("---","");let m=[],p=Bn;for(let g of Ct){let b=Le(d,g);if(b!=null){m=An(Ne(b)),p=g;break}}let h=new Set;if(typeof m=="string")h.add(m),m=[m];else if(m!=null)for(let g of m)h.add(g);else m=[];for(let g of o){let b=g.trim().substring(1);!h.has(b)&&!e.tagsToIgnore.includes(b)&&(h.add(b),m.push(b))}return`---
${he(d,p,Se(m,e.tagArrayStyle,e.defaultEscapeCharacter,e.removeUnnecessaryEscapeCharsForMultiLineArrays))}---`});let l=[],c=t.length-r.text.length;if(e.howToHandleExistingTags!=="Nothing")for(let d of a){if(e.tagsToIgnore.includes(d[2].substring(1)))continue;let m=s.editRangeToSource({startIndex:d.index,endIndex:d.index+d[0].length}),p=r.sourceToProjection(m.startIndex)+c,h=r.sourceToProjection(m.endIndex)+c;e.howToHandleExistingTags==="Remove hashtag"?(p+=d[1].length,l.push({startIndex:p,endIndex:p+1,value:""})):(d.index===0&&d[1]===""&&c>0&&p--,l.push({startIndex:p,endIndex:h,value:""}))}t=J(t,l),t=t.replace(/(\n---)( |\t)+/,"$1");let u=[];for(let d of Ue(r.text,t)){let m=r.editRangeToSource(d);m&&u.push({...m,value:d.value})}return J(r.source,u)}get optionBuilders(){return[new de({OptionsClass:ii,nameKey:"rules.move-tags-to-yaml.how-to-handle-existing-tags.name",descriptionKey:"rules.move-tags-to-yaml.how-to-handle-existing-tags.description",optionsKey:"howToHandleExistingTags",records:[{value:"Nothing",description:"Leaves tags in the body of the file alone"},{value:"Remove hashtag",description:"Removes `#` from tags in content body after moving them to the YAML frontmatter"},{value:"Remove whole tag",description:"Removes the whole tag in content body after moving them to the YAML frontmatter. _Note that this removes the first space prior to the tag as well_"}]}),new Ae({OptionsClass:ii,nameKey:"rules.move-tags-to-yaml.tags-to-ignore.name",descriptionKey:"rules.move-tags-to-yaml.tags-to-ignore.description",emptyStateKey:"rules.move-tags-to-yaml.tags-to-ignore.empty-state",fieldNamePlaceholderKey:"rules.move-tags-to-yaml.tags-to-ignore.placeholder-text",optionsKey:"tagsToIgnore",validator:Ec})]}};Wm=I(x1),Ps=O(Wm,0,"MoveTagsToYaml",lk,Ps),L(Wm,1,Ps);var jc=class{constructor(){this.noBareURIs=!1}},Wc="'\"\u2018\u2019\u201C\u201D`[]",L1=["http","ftp","https","smtp"],ck,jm,E1;ck=[w.register];var zs=class extends(E1=w){constructor(){super({nameKey:"rules.no-bare-urls.name",descriptionKey:"rules.no-bare-urls.description",type:"Content",ruleIgnoreTypes:[y.code,y.math,y.yaml,y.link,y.wikiLink,y.tag,y.image,y.inlineCode,y.anchorTag,y.html]})}get OptionsClass(){return jc}apply(t,e,i){let r=[],s=bg(t).toReversed();if(s){let a=[];for(let o of s)a.push({match:t.substring(o.start.offset,o.end.offset),urlStart:o.start.offset,urlEnd:o.end.offset});r.push(...this.handleMatches(t,a,!1,i))}if(e.noBareURIs){let a=t.match(Og);if(a){let o=0,l=[];for(let u of a){let d=u,m=t.indexOf(d,o),p=m+d.length;o=p,l.push({match:d,urlStart:m,urlEnd:p})}let c=new Et(r);for(let u of this.handleMatches(t,l,!0,i))c.isProtected(u.startIndex,u.endIndex)||r.push(u)}}return J(t,r)}handleMatches(t,e,i,r){let s=[];for(let a of e){let o=a.match,l=a.urlStart,c=a.urlEnd;if(r.isProtected(l,c))continue;o.charAt(0)==="<"&&(o=o.substring(1),l++),o.charAt(o.length-1)===">"&&(o=o.substring(0,o.length-1),c--);let u=l===0?void 0:Hn(t,r,l-1,l).slice(-1),d=c>=t.length?void 0:Hn(t,r,c,c+1).charAt(0),m=Tt(o,"(");if(m!=0&&m!=Tt(o,")")&&d==")"?(o+=d,c++,d=c>=t.length?void 0:Hn(t,r,c,c+1).charAt(0)):m==0&&o.endsWith(")")&&(d=")",c--,o=o.substring(0,o.length-1)),!this.skipMatch(u,d,o,i)){if(u!=null&&u==="<"&&d!=null&&d===">"){let p=l-1;for(;p>0&&t.charAt(p-1)==="<";)p--;let h=c;for(;h<t.length-1&&t.charAt(h+1)===">";)h++;r.isProtected(p,h+1)||this.addReplacement(s,{startIndex:p,endIndex:h+1,value:"<"+o+">"});continue}r.isProtected(l,l+o.length)||this.addReplacement(s,{startIndex:l,endIndex:l+o.length,value:"<"+o+">"})}}return s}addReplacement(t,e){let i=t[t.length-1];i&&e.startIndex<i.endIndex||t.push(e)}skipMatch(t,e,i,r){let s=t!=null&&Wc.includes(t)||Wc.includes(i.charAt(0)),a=e!=null&&Wc.includes(e)||Wc.includes(i.charAt(i.length-1));return s&&a?!0:r?L1.includes(i.substring(0,i.indexOf(":"))):!1}get optionBuilders(){return[new V({OptionsClass:jc,nameKey:"rules.no-bare-urls.no-bare-uris.name",descriptionKey:"rules.no-bare-urls.no-bare-uris.description",optionsKey:"noBareURIs"})]}};jm=I(E1),zs=O(jm,0,"NoBareUrls",ck,zs),L(jm,1,zs);var Ws=class{constructor(){this.numberStyle="ascending";this.listEndStyle="."}},dk,Um,M1;dk=[w.register];var qs=class extends(M1=w){constructor(){super({nameKey:"rules.ordered-list-style.name",descriptionKey:"rules.ordered-list-style.description",type:"Content",ruleIgnoreTypes:[y.code,y.math,y.yaml,y.tag]})}get OptionsClass(){return Ws}apply(t,e,i){return mg(t,e.numberStyle,e.listEndStyle,e.preserveStart,i)}get optionBuilders(){return[new de({OptionsClass:Ws,nameKey:"rules.ordered-list-style.number-style.name",descriptionKey:"rules.ordered-list-style.number-style.description",optionsKey:"numberStyle",records:[{value:"ascending",description:"Makes sure ordered list items are ascending (i.e. 1, 2, 3, etc.)"},{value:"lazy",description:"Makes sure ordered list item indicators all are the same"},{value:"preserve",description:"Preserves ordered list item indicators as they are"}]}),new de({OptionsClass:Ws,nameKey:"rules.ordered-list-style.listLine truncated
(?:(?:[ \v\f\r \xA0\u2000-\u200B\u2028-\u2029\u3000]+)?
){1,}${i}$`,"gm"),s,a=e;do s=a.match(r),a=a.replaceAll(r,`$1
$4`);while(s);return a}}get OptionsClass(){return ap}apply(e,i,r){let s=r.projection(),a=s.text,o=`(( |\\t)*- ${wr}( |\\t)+.+)`;a=this.replaceEmptyLinesBetweenList(a,o),a=this.replaceEmptyLinesBetweenList(a,"(( |\\t)*\\d+\\.( |\\t)+.+)"),a=this.replaceEmptyLinesBetweenList(a,"(( |\\t)*\\+( |\\t)+.+)");let u=`(( |\\t)*-(?! ${wr})( |\\t)+.+)`;a=this.replaceEmptyLinesBetweenList(a,u),a=this.replaceEmptyLinesBetweenList(a,"(( |\\t)*\\*( |\\t)+.+)");let m=[];for(let p of Ue(s.text,a)){let h=s.editRangeToSource(p);h&&m.push({...h,value:p.value})}return J(e,m)}get optionBuilders(){return[]}};sp=I(H1),Js=O(sp,0,"RemoveEmptyLinesBetweenListMarkersAndChecklists",xk,Js),L(sp,1,Js);var lp=class{},Lk,op,V1;Lk=[w.register];var Zs=class extends(V1=w){constructor(){super({nameKey:"rules.remove-empty-list-markers.name",descriptionKey:"rules.remove-empty-list-markers.description",type:"Content",ruleIgnoreTypes:[y.code,y.math,y.yaml,y.link,y.wikiLink,y.tag]})}get OptionsClass(){return lp}apply(t,e,i){let r=i.projection(),s=r.text,a=new RegExp(`^${Wa}(-|\\*|\\+|\\d+[.)]|- (\\[(.)\\]))\\s*?$`,"gm");s=s.replace(new RegExp(a.source+"\\n","gm"),""),s=s.replace(new RegExp("\\n"+a.source,"gm"),""),s=s.replace(a,"");let o=[];for(let l of Ue(r.text,s)){let c=r.editRangeToSource(l);c&&o.push({...c,value:l.value})}return J(t,o)}get optionBuilders(){return[]}};op=I(V1),Zs=O(op,0,"RemoveEmptyListMarkers",Lk,Zs),L(op,1,Zs);var dp=class{},Sk,cp,Q1;Sk=[w.register];var Xs=class extends(Q1=w){constructor(){super({nameKey:"rules.remove-hyphenated-line-breaks.name",descriptionKey:"rules.remove-hyphenated-line-breaks.description",type:"Content",ruleIgnoreTypes:[y.code,y.math,y.yaml,y.link,y.wikiLink,y.tag]})}get OptionsClass(){return dp}apply(t,e,i){let r=(s,a)=>({startIndex:a,endIndex:a+s[0].length,value:""});return ke(t,le(t,/\b[-‐] \b/g,i,{editRange:r,guardRange:r}))}get optionBuilders(){return[]}};cp=I(Q1),Xs=O(cp,0,"RemoveHyphenatedLineBreaks",Sk,Xs),L(cp,1,Xs);var mp=class{},Ek,up,Z1;Ek=[w.register];var Hi=class extends(Z1=w){constructor(){super({nameKey:"rules.remove-hyphens-on-paste.name",descriptionKey:"rules.remove-hyphens-on-paste.description",type:"Paste"})}get OptionsClass(){return mp}apply(t,e){return t.replace(/([^\s-])[-‐]\s+\n?(?=\w)/g,"$1")}get optionBuilders(){return[]}};up=I(Z1),Hi=O(up,0,"RemoveHyphensOnPaste",Ek,Hi),L(up,1,Hi);var fp=class{},Tk,pp,e0;Tk=[w.register];var $i=class extends(e0=w){constructor(){super({nameKey:"rules.remove-leading-or-trailing-whitespace-on-paste.name",descriptionKey:"rules.remove-leading-or-trailing-whitespace-on-paste.description",type:"Paste"})}get OptionsClass(){return fp}apply(t,e){return t.replace(/^[\n ]+|\s+$/g,"")}get optionBuilders(){return[]}};pp=I(e0),$i=O(pp,0,"RemoveLeadingOrTrailingWhitespaceOnPaste",Tk,$i),L(pp,1,$i);var gp=class{},Mk,hp,n0;Mk=[w.register];var Vi=class extends(n0=w){constructor(){super({nameKey:"rules.remove-leftover-footnotes-from-quote-on-paste.name",descriptionKey:"rules.remove-leftover-footnotes-from-quote-on-paste.description",ruleIgnoreTypes:[y.wikiLink,y.link,y.image],type:"Paste"})}get OptionsClass(){return gp}apply(t,e,i){let r=(a,o)=>({startIndex:o+a[1].length,endIndex:o+a[0].length,value:""}),s=le(t,/(\D)[.,]\d+/g,i,{guardRange:r,editRange:r});return J(t,s)}get optionBuilders(){return[]}};hp=I(n0),Vi=O(hp,0,"RemoveLeftoverFootnotesFromQuoteOnPaste",Mk,Vi),L(hp,1,Vi);var bp=class{},Ok,yp,r0;Ok=[w.register];var ea=class extends(r0=w){constructor(){super({nameKey:"rules.remove-link-spacing.name",descriptionKey:"rules.remove-link-spacing.description",type:"Spacing"})}get OptionsClass(){return bp}apply(t,e,i){return t=rg(t,i),Yg(t)}get optionBuilders(){return[]}};yp=I(r0),ea=O(yp,0,"RemoveLinkSpacing",Ok,ea),L(yp,1,ea);var vp=class{},Ck,kp,a0;Ck=[w.register];var Gi=class extends(a0=w){constructor(){super({nameKey:"rules.remove-multiple-blank-lines-on-paste.name",descriptionKey:"rules.remove-multiple-blank-lines-on-paste.description",type:"Paste"})}get OptionsClass(){return vp}apply(t,e){return t.replace(Zr,`
`)}get optionBuilders(){return[]}};kp=I(a0),Gi=O(kp,0,"RemoveMultipleBlankLinesOnPaste",Ck,Gi),L(kp,1,Gi);var wp=class{},Ik,Ap,l0;Ik=[w.register];var ta=class extends(l0=w){constructor(){super({nameKey:"rules.remove-multiple-spaces.name",descriptionKey:"rules.remove-multiple-spaces.description",type:"Content",ruleIgnoreTypes:[y.code,y.inlineCode,y.math,y.inlineMath,y.yaml,y.link,y.wikiLink,y.tag,y.table,y.image]})}get OptionsClass(){return wp}apply(t,e,i){let r=(a,o)=>({startIndex:o+a[1].length,endIndex:o+a[0].length-a[3].length,value:" "}),s=le(t,/(?!^>)([^\s])( ){2,}([^\s])/gm,i.combinedWith([y.list]),{editRange:r,guardRange:r});for(let{position:a}of yi(t)){let o=a.start.offset;for(;o>0&&t.charAt(o-1).trim()==="";)o--;(o===0||t.charAt(o-1).trim()!=="")&&o++,bi.test(t.substring(o,a.end.offset))&&(o+=4),s.push(...le(t.substring(o,a.end.offset),/([^\s])( ){2,}([^\s])/gm,i,{editRange:r,guardRange:r},o))}return s.sort((a,o)=>a.startIndex-o.startIndex),ke(t,s)}get optionBuilders(){return[]}};Ap=I(l0),ta=O(Ap,0,"RemoveMultipleSpaces",Ik,ta),L(Ap,1,ta);var Cr=class{constructor(){this.includeFullwidthForms=!0;this.includeCJKSymbolsAndPunctuation=!0;this.includeDashes=!0;this.otherSymbols=""}},Rk,xp,d0;Rk=[w.register];var na=class extends(d0=w){constructor(){super({nameKey:"rules.remove-space-around-characters.name",descriptionKey:"rules.remove-space-around-characters.description",type:"Spacing",ruleIgnoreTypes:[y.code,y.inlineCode,y.math,y.yaml,y.link,y.wikiLink,y.tag]})}get OptionsClass(){return Cr}apply(t,e,i){let r="";if(e.includeFullwidthForms&&(r+="\uFF01-\uFF5E"),e.includeCJKSymbolsAndPunctuation&&(r+="\u3000-\u303F"),e.includeDashes&&(r+="\u2013\u2014"),r+=Mt(e.otherSymbols),!r)return t;let s=new RegExp(`([ ])+([${r}])`,"g"),a=new RegExp(`([${r}])([ ])+`,"g"),o=function(u,d,m){return[...le(u,s,m,{editRange:(p,h)=>({startIndex:h,endIndex:h+p[0].length-p[2].length,value:""}),guardRange:(p,h)=>({startIndex:h,endIndex:h+p[0].length})},d),...le(u,a,m,{editRange:(p,h)=>({startIndex:h+p[1].length,endIndex:h+p[0].length,value:""}),guardRange:(p,h)=>({startIndex:h,endIndex:h+p[0].length})},d)]},l=o(t,0,i.combinedWith([y.list,y.heading]));for(let{position:u}of yi(t)){let d=u.start.offset;for(;d>0&&t.charAt(d-1).trim()==="";)d--;(d===0||t.charAt(d-1).trim()!=="")&&d++,bi.test(t.substring(d,u.end.offset))&&(d+=4),l.push(...o(t.substring(d,u.end.offset),d,i))}for(let{position:u,text:d}of Xh(t)){let p=t.substring(u.start.offset,u.end.offset).indexOf(d);p!==-1&&l.push(...o(d,u.start.offset+p,i))}let c=new Et(l).ranges.map(u=>({...u,value:""}));return ke(t,c)}get optionBuilders(){return[new V({nameKey:"rules.remove-space-around-characters.include-fullwidth-forms.name",descriptionKey:"rules.remove-space-around-characters.include-fullwidth-forms.description",OptionsClass:Cr,optionsKey:"includeFullwidthForms"}),new V({nameKey:"rules.remove-space-around-characters.include-cjk-symbols-and-punctuation.name",descriptionKey:"rules.remove-space-around-characters.include-cjk-symbols-and-punctuation.description",OptionsClass:Cr,optionsKey:"includeCJKSymbolsAndPunctuation"}),new V({nameKey:"rules.remove-space-around-characters.include-dashes.name",descriptionKey:"rules.remove-space-around-characters.include-dashes.description",OptionsClass:Cr,optionsKey:"includeDashes"}),new Te({nameKey:"rules.remove-space-around-characters.other-symbols.name",descriptionKey:"rules.remove-space-around-characters.other-symbols.description",OptionsClass:Cr,optionsKey:"otherSymbols"})]}};xp=I(d0),na=O(xp,0,"RemoveSpaceAroundCharacters",Rk,na),L(xp,1,na);var Mo=class{constructor(){this.charactersToRemoveSpacesBefore=",!?;:).\u2019\u201D]";this.charactersToRemoveSpacesAfter="\xBF\xA1\u2018\u201C(["}},Nk,Lp,m0;Nk=[w.register];var ia=class extends(m0=w){constructor(){super({nameKey:"rules.remove-space-before-or-after-characters.name",descriptionKey:"rules.remove-space-before-or-after-characters.description",type:"Spacing",ruleIgnoreTypes:[y.code,y.math,y.yaml,y.link,y.wikiLink,y.tag]})}get OptionsClass(){return Mo}apply(t,e,i){let r=Mt(e.charactersToRemoveSpacesBefore),s=Mt(e.charactersToRemoveSpacesAfter);if(!r&&!s)return t;let a=new RegExp(`([ ])+([${r}])`,"g"),o=new RegExp(`([${s}])([ ])+`,"g"),l=[],c=function(m,p,h){l.push(...le(m,a,h,{editRange:(f,g)=>({startIndex:g,endIndex:g+f[0].length-f[2].length,value:""}),guardRange:(f,g)=>({startIndex:g,endIndex:g+f[0].length})},p)),l.push(...le(m,o,h,{editRange:(f,g)=>({startIndex:g+f[1].length,endIndex:g+f[0].length,value:""}),guardRange:(f,g)=>({startIndex:g,endIndex:g+f[0].length})},p))};c(t,0,i.combinedWith([y.list,y.html,y.heading]));let u=0;for(let m of t.matchAll(cn)){let p=t.indexOf(m[0],u);if(!m[4]||m[4].trim()==""){u=p+m[0].length;continue}let h=p+(m[1]?.length??0)+(m[2]?.length??0)+(m[3]?.length??0);c(m[4],h,i),u=p+m[0].length}for(let{position:m}of yi(t)){let p=m.start.offset;for(;p>0&&t.charAt(p-1).trim()==="";)p--;(p===0||t.charAt(p-1).trim()!=="")&&p++,bi.test(t.substring(p,m.end.offset))&&(p+ Line truncated
`,"").replace(`
---`,""));if(!r)return i;for(let s of It)if(e.sortAliasKey&&Object.keys(r).includes(s)){i=he(i,s,Se(wn(this.sortArray(Ne(Le(i,s)),e.sortOrder)),e.aliasArrayStyle,e.defaultEscapeCharacter,e.removeUnnecessaryEscapeCharsForMultiLineArrays,!0));break}for(let s of Ct)if(e.sortTagKey&&Object.keys(r).includes(s)){i=he(i,s,Se(An(this.sortArray(Ne(Le(i,s)),e.sortOrder)),e.tagArrayStyle,e.defaultEscapeCharacter,e.removeUnnecessaryEscapeCharsForMultiLineArrays));break}if(e.sortArrayKeys){let s=[...It,...Ct,...e.ignoreSortArrayKeys];for(let a of Object.keys(r)){if(s.includes(a)||!Array.isArray(r[a])||r[a].length!==0&&typeof r[a][0]=="object"&&r[a][0]!==null)continue;let o=Le(i,a),l="single-line";o.includes(`
`)&&(l="multi-line");let c=this.sortArray(Ne(o),e.sortOrder);i=he(i,a,Se(c,l,e.defaultEscapeCharacter,e.removeUnnecessaryEscapeCharsForMultiLineArrays))}}return i})}sortArray(t,e){return t==null||typeof t=="string"||t.length<=1||(t.sort(function(i,r){let s=i.toLowerCase().localeCompare(r.toLowerCase());return s===0?i.localeCompare(r):s}),e==="Ascending Alphabetical")||t.reverse(),t}get optionBuilders(){return[new V({OptionsClass:Yt,nameKey:"rules.sort-yaml-array-values.sort-alias-key.name",descriptionKey:"rules.sort-yaml-array-values.sort-alias-key.description",optionsKey:"sortAliasKey"}),new V({OptionsClass:Yt,nameKey:"rules.sort-yaml-array-values.sort-tag-key.name",descriptionKey:"rules.sort-yaml-array-values.sort-tag-key.description",optionsKey:"sortTagKey"}),new V({OptionsClass:Yt,nameKey:"rules.sort-yaml-array-values.sort-array-keys.name",descriptionKey:"rules.sort-yaml-array-values.sort-array-keys.description",optionsKey:"sortArrayKeys"}),new Ae({OptionsClass:Yt,nameKey:"rules.sort-yaml-array-values.ignore-keys.name",descriptionKey:"rules.sort-yaml-array-values.ignore-keys.description",emptyStateKey:"rules.sort-yaml-array-values.ignore-keys.empty-state",fieldNamePlaceholderKey:"rules.sort-yaml-array-values.ignore-keys.placeholder-text",optionsKey:"ignoreSortArrayKeys",validator:Nt}),new de({OptionsClass:Yt,nameKey:"rules.sort-yaml-array-values.sort-order.name",descriptionKey:"rules.sort-yaml-array-values.sort-order.description",optionsKey:"sortOrder",records:[{value:"Ascending Alphabetical",description:"Sorts the array values from a to z"},{value:"Descending Alphabetical",description:"Sorts the array values from z to a"}]})]}};Tp=I(b0),aa=O(Tp,0,"SortYamlArrayValues",Pk,aa),L(Tp,1,aa);var Op=class{},zk,Mp,v0;zk=[w.register];var oa=class extends(v0=w){constructor(){super({nameKey:"rules.space-after-list-markers.name",descriptionKey:"rules.space-after-list-markers.description",type:"Spacing",ruleIgnoreTypes:[y.code,y.math,y.yaml,y.link,y.wikiLink,y.tag]})}get OptionsClass(){return Op}apply(t,e,i){let r={editRange:(a,o)=>({startIndex:o+a[1].length,endIndex:o+a[0].length,value:" "}),guardRange:(a,o)=>({startIndex:o,endIndex:o+a[0].length})},s=le(t,/^(\s*\d+\.|\s*[-+*])[^\S\r\n]+/gm,i,r);return s.push(...le(t,/^(\s*[-+*]\s+\[[ xX]\])[^\S\r\n]+/gm,i,r)),J(t,s)}get optionBuilders(){return[]}};Mp=I(v0),oa=O(Mp,0,"SpaceAfterListMarkers",zk,oa),L(Mp,1,oa);var Oo=class{constructor(){this.englishNonLetterCharactersAfterCJKCharacters=`-+'"([\xA5$`;this.englishNonLetterCharactersBeforeCJKCharacters=`-+;:'"\xB0%$)]`}},qk,Cp,w0;qk=[w.register];var la=class extends(w0=w){constructor(){super({nameKey:"rules.space-between-chinese-japanese-or-korean-and-english-or-numbers.name",descriptionKey:"rules.space-between-chinese-japanese-or-korean-and-english-or-numbers.description",type:"Spacing",ruleIgnoreTypes:[y.code,y.inlineCode,y.yaml,y.image,y.link,y.wikiLink,y.tag,y.math,y.inlineMath,y.html]})}get OptionsClass(){return Oo}apply(t,e,i){let r=this.buildHeadRegex(e.englishNonLetterCharactersAfterCJKCharacters),s=this.buildTailRegex(e.englishNonLetterCharactersBeforeCJKCharacters),a=on.for(t).protectedRangesFor([y.link,y.inlineMath,y.inlineCode,y.wikiLink]),o=(m,p,h)=>{let f=[];for(let g of[r,s])f.push(...le(m,g,h,{editRange:(b,k)=>({startIndex:k+b[1].length,endIndex:k+b[0].length-b[3].length,value:" "}),guardRange:(b,k)=>({startIndex:k,endIndex:k+b[0].length})},p));return f},l=o(t,0,i.combinedWith([y.italics,y.bold])),c=/[\p{sc=Han}\p{sc=Katakana}\p{sc=Hiragana}\p{sc=Hangul}]( *)$/u,u=/^( *)[\p{sc=Han}\p{sc=Katakana}\p{sc=Hiragana}\p{sc=Hangul}]/u;for(let m of a.ranges){let p=m.startIndex;for(;p>0&&t.charAt(p-1)===" ";)p--;let h=t.substring(Math.max(0,p-2),m.startIndex).match(c);h&&!i.isProtected(m.startIndex-h[0].length,m.startIndex)&&l.push({startIndex:p,endIndex:m.startIndex,value:" "});let f=m.endIndex;for(;f<t.length&&t.charAt(f)===" ";)f++;let g=t.substring(m.endIndex,f+2).match(u);g&&!i.isProtected(m.endIndex,m.endIndex+g[0].length)&&l.push({startIndex:m.endIndex,endIndex:f,value:" "})}l.push(...sg(t,o,i)),l.push(...ag(t,o,i)),l.sort((m,p)=>m.startIndex-p.startIndex||m.endIndex-p.endIndex);let d=l.filter((m,p)=>{let h=l[p-1];return!h||m.startIndex!==h.startIndex||m.endIndex!==h.endIndex});return ke(t,d)}buildHeadRegex(t){t&&t!==""&&(t=t.replaceAll(/\s/g,""));let e="";return t&&t.length!=0&&(e=`|[${Mt(t)}]`),new RegExp(`(\\p{sc=Han}|\\p{sc=Katakana}|\\p{sc=Hiragana}|\\p{sc=Hangul})( *)(\\[[^[]*\\]\\(.*\\)|\`[^\`]*\`|\\w+${e}|\\*[^*])`,"gmu")}buildTailRegex(t){t&&t!==""&&(t=t.replaceAll(/\s/g,""));let e="";return t&&t.length!=0&&(e=`|[${Mt(t)}]`),new RegExp(`(\\[[^[]*\\]\\(.*\\)|\`[^\`]*\`|\\w+${e}|[^*]\\*)( *)(\\p{sc=Han}|\\p{sc=Katakana}|\\p{sc=Hiragana}|\\p{sc=Hangul})`,"gmu")}get optionBuilders(){return[new Te({OptionsClass:Oo,nameKey:"rules.space-between-chinese-japanese-or-korean-and-english-or-numbers.english-symbols-punctuation-before.name",descriptionKey:"rules.space-between-chinese-japanese-or-korean-and-engLine truncated
${e.dateCreatedKey}: [^
]+
`,s=`
${e.dateCreatedKey}:[ ]*
`,a=new RegExp(s),o=new RegExp(r),l=(0,Qt.moment)(e.fileCreatedTime);l.locale(e.locale);let c=e.convertToUTC?l.utc().format(e.format):l.format(e.format),u=`
${e.dateCreatedKey}: ${c}`,d=o.test(t);if(!d&&a.test(t))t=t.replace(a,ft(u)+`
`),i=!0;else if(d){if(d){let m=this.getYAMLTimestampString(t,o,e.dateCreatedKey),p=(0,Pp.default)(m);if(e.dateCreatedSourceOfTruth=="frontmatter"&&e.format!==p){let h=this.parseValueToCurrentFormatIfPossible(m,e.format,e.locale,e.convertToUTC);if(h==null)throw new Error(A("logs.invalid-date-format-error").replace("{DATE}",m).replace("{FILE_NAME}",e.fileName));let f=e.convertToUTC?h.utc().format(e.format):h.format(e.format);if(f!==m){let g=`
${e.dateCreatedKey}: ${f}`;t=t.replace(o,ft(g)+`
`),i=!0}}else if(e.dateCreatedSourceOfTruth!="frontmatter"){let h=(0,Qt.moment)(m,e.format,e.locale);(h==null||!h.isValid()||e.format!==""&&h.format(e.format)!=m)&&(t=t.replace(o,ft(u)+`
`),i=!0)}}}else{let m=t.indexOf(`
---`);t=Ia(t,m,`
${e.dateCreatedKey}: ${c}`),i=!0}return[t,i]}handleDateModifiedValue(t,e,i){let r=`
${i.dateModifiedKey}: [^
]+
`,s=`
${i.dateModifiedKey}:[ ]*
`,a=new RegExp(s),o=new RegExp(r),l=(0,Qt.moment)(i.fileModifiedTime);l.locale(i.locale);let c=i.convertToUTC?i.currentTime.utc().format(i.format):i.currentTime.format(i.format),u=`
${i.dateModifiedKey}: ${c}`,d=o.test(t);if(d){let m=this.getYAMLTimestampString(t,o,i.dateModifiedKey),p=(0,Qt.moment)(m,i.format,i.locale);(e||p==null||!p.isValid()||p.format(i.format)!=m||i.dateModifiedSourceOfTruth!="user or Linter edits"&&this.getTimeDifferenceInSeconds(p,l,i)>5)&&(t=t.replace(o,ft(u)+`
`))}else if(a.test(t))t=t.replace(a,ft(u)+`
`);else if(!d){let m=t.indexOf(`
---`);t=Ia(t,m,u)}return t}parseValueToCurrentFormatIfPossible(t,e,i,r){if(t==null)return null;let s=r?Qt.moment.utc(t,e,i,!0):(0,Qt.moment)(t,e,i,!0);if(s!=null&&s.isValid())return s;let a=(0,Pp.default)(t);if(a!=null){let o=r?Qt.moment.utc(t,a):(0,Qt.moment)(t,a);o.locale(i);let l=r?o.utc().format(e):o.format(e);return r?Qt.moment.utc(l,e,i,!0):(0,Qt.moment)(l,e,i,!0)}return null}getYAMLTimestampString(t,e,i){return t.match(e)[0].replace(i+":","").trim()}getTimeDifferenceInSeconds(t,e,i){let r=(0,Qt.moment)(e.format(i.format),i.format,i.locale,!0);return Math.abs(t.diff(r,"seconds"))}get optionBuilders(){return[new V({OptionsClass:Pe,nameKey:"rules.yaml-timestamp.date-created.name",descriptionKey:"rules.yaml-timestamp.date-created.description",optionsKey:"dateCreated"}),new Te({OptionsClass:Pe,nameKey:"rules.yaml-timestamp.date-created-key.name",descriptionKey:"rules.yaml-timestamp.date-created-key.description",optionsKey:"dateCreatedKey"}),new de({OptionsClass:Pe,nameKey:"rules.yaml-timestamp.date-created-source-of-truth.name",descriptionKey:"rules.yaml-timestamp.date-created-source-of-truth.description",optionsKey:"dateCreatedSourceOfTruth",records:[{value:"file system",description:"The file system date created value is used to set the value of date created in the frontmatter"},{value:"frontmatter",description:"When a value is present in the frontmatter for date created, this value is used as the value for the date created"}]}),new V({OptionsClass:Pe,nameKey:"rules.yaml-timestamp.date-modified.name",descriptionKey:"rules.yaml-timestamp.date-modified.description",optionsKey:"dateModified"}),new Te({OptionsClass:Pe,nameKey:"rules.yaml-timestamp.date-modified-key.name",descriptionKey:"rules.yaml-timestamp.date-modified-key.description",optionsKey:"dateModifiedKey"}),new de({OptionsClass:Pe,nameKey:"rules.yaml-timestamp.date-modified-source-of-truth.name",descriptionKey:"rules.yaml-timestamp.date-modified-source-of-truth.description",optionsKey:"dateModifiedSourceOfTruth",records:[{value:"file system",description:"The file system date modified value is used to set the value of date modified in the frontmatter"},{value:"user or Linter edits",description:"When a value is present in the frontmatter for date modified, date modified is kept as is unless the Linter makes a change to a note or the user edits a note with the setting `{NAME}` set to something other than `{NEVER}`.".replace("{NAME}",A("rules.yaml-timestamp.update-on-file-contents-updated.name")).replace("{NEVER}",A("enums.never"))}]}),new xc({OptionsClass:Pe,nameKey:"rules.yaml-timestamp.format.name",descriptionKey:"rules.yaml-timestamp.format.description",optionsKey:"format"}),new V({OptionsClass:Pe,nameKey:"rules.yaml-timestamp.convert-to-utc.name",descriptionKey:"rules.yaml-timestamp.convert-to-utc.description",optionsKey:"convertToUTC"}),new de({OptionsClass:Pe,nameKey:"rules.yaml-timestamp.update-on-file-contents-updated.name",descriptionKey:"rules.yaml-timestamp.update-on-file-contents-updated.description",optionsKey:"timestampUpdateOnFileContentUpdated",records:[{value:"never",description:"never"},{value:"after 5 seconds",description:"after 5 seconds"},{value:"after 10 seconds",description:"after 10 seconds"},{value:"after 15 seconds",description:"after 15 seconds"},{value:"after 30 seconds",description:"after 30 seconds"},{value:"after 1 minute",description:"after 1 minute"}]})]}};Kp=I(zE),zn=O(Kp,0,"YamlTimestamp",hv,zn),L(Kp,1,zn);var gv,yv,bv,kv,_t;kv=[w.noSettingControl()],bv=[w.noSettingControl()],yv=[w.noSettingControl()],gv=[w.noSettingControl()];var Kt=class{constructor(){this.preserveExistingAliasesSectionStyle=!0;this.keepAliasThatMatchesTheFilename=!1;this.removeAliasKeyWhenEmpty=!0;this.useYamlKeyToKeepTrackOfOldFilenameOrHeading=!0;this.aliasHelperKey=ju;this.aliasArrayStyle=L(_t,8,this,"multi-line"),L(_t,11,this);this.fileName=L(_t,12,this),L(_t,15,this);this.defaultEscapeCharacter=L(_t,16,this,'"'),L(_t,19,this);this.removeUnnecessaryEscapeCharsForMultiLineArrays=L(_t,20,this,!1),L(_t,23,this)}};_t=I(null),O(_t,5,"aliasArrayStyle",kv,Kt),O(_t,5,"fileName",bv,Kt),O(_t,5,"defaultEscapeCharacter",yv,Kt),O(_t,5,"removeUnnecessaryEscapeCharsForMultiLineArrays",gv,Kt),oe(_t,Kt);var vv,zp,jE;vv=[w.register];var Zi=class extends(jE=w){constructor(){super({nameKey:"rules.yaml-title-alias.name",descriptionKey:"rules.yaml-title-alias.description",type:"YAML",hasSpecialExecutionOrder:!0})}get OptionsClass(){return Kt}apply(t,e,i){let[r,s]=this.getTitleInfo(t,e.fileName,e.aliasArrayStyle,e.defaultEscapeCharacter,i);t=$t(t);let a,o=t.match(Ze)[1],l=!e.keepAliasThatMatchesTheFilename&&r===e.fileName,c=o.replace(`---
`,"").replace(`
---`,""),u=dt(o),d=e.aliasHelperKey??ju;d.endsWith(":")&&(d=d.substring(0,d.length-1)),a=u[d]??null,a!=null&&(a=a+"",a=nt(a,e.defaultEscapeCharacter,this.forceEscape(a,e.aliasArrayStyle)));let m=null,p=Object.keys(u);for(let g of It)if(p.includes(g)){m=g;break}if(m!=null){let g=Le(c,m),b="multi-line",k=g==="",x=!1;!g.includes(`
`)&&!(g==="[]"&&e.aliasArrayStyle==="multi-line")&&(g.match(/^\[.*\]/)===null?(b="single string to single-line",x=!0):b="single-line");let E=wn(Ne(g)),C=this.getNewAliasValue(E,l,s,a);C===""?e.removeAliasKeyWhenEmpty&&(c=po(c,m)):e.preserveExistingAliasesSectionStyle?!k&&(x&&s==C||!x||E==C)?c=he(c,m,Se(C,b,e.defaultEscapeCharacter,e.removeUnnecessaryEscapeCharsForMultiLineArrays,!0)):c=he(c,m,Se(C,e.aliasArrayStyle,e.defaultEscapeCharacter,e.removeUnnecessaryEscapeCharsForMultiLineArrays,!0)):c=he(c,m,Se(C,e.aliasArrayStyle,e.defaultEscapeCharacter,e.removeUnnecessaryEscapeCharsForMultiLineArrays,!0))}else l||(c=he(c,Ti,Se(s,e.aliasArrayStyle,e.defaultEscapeCharacter,e.removeUnnecessaryEscapeCharsForMultiLineArrays,!0)));!e.useYamlKeyToKeepTrackOfOldFilenameOrHeading||l?c=po(c,d):c=he(c,d,` ${s}`);let h=`---
${o}---`,f=`---
${c}---`;return c===""&&(f=""),t=t.replace(h,f),c===""&&(t=t.trimStart()),t}getTitleInfo(t,e,i,r,s){let a=yl(t,s.combinedWith([y.code,y.math,y.yaml,y.tag]));a=a||e;let o=nt(a,r,this.forceEscape(a,i));return[a,o]}forceEscape(t,e){return Go(t)||t.includes(",")&&(e==="single-line"||e==="single string to single-line"||e==="single string comma delimited")}getNewAliasValue(t,e,i,r){if(t==null)return e?"":i;if(typeof t=="string")e?t===i&&(t=""):r===t?t=i:t=[i,t];else if(r!==null){let s=t.indexOf(r);s===-1&&Ei(r)&&(s=t.indexOf(r.substring(1,r.length-1))),s!==-1?e?t.splice(s,1):t[s]=i:t=[i,...t]}else{let s=t.indexOf(i);s!==-1?e&&t.splice(s,1):e||(t=[i,...t])}return t===""||t.length===0?"":t}get optionBuilders(){return[new V({OptionsClass:Kt,nameKey:"rules.yaml-title-alias.preserve-existing-alias-section-style.name",descriptionKey:"rules.yaml-title-alias.preserve-existing-alias-section-style.description",optionsKey:"preserveExistingAliasesSectionStyle"}),new V({OptionsClass:Kt,nameKey:"rules.yaml-title-alias.keep-alias-that-matches-the-filename.name",descriptionKey:"rules.yaml-title-alias.keep-alias-that-matches-the-filename.description",optionsKey:"keepAliasThatMatchesTheFilename"}),new V({OptionsClass:Kt,nameKey:"rules.yaml-title-alias.use-yaml-key-to-keep-track-of-old-filename-or-heading.name",descriptionKey:"rules.yaml-title-alias.use-yaml-key-to-keep-track-of-old-filename-or-heading.description",optionsKey:"useYamlKeyToKeepTrackOfOldFilenameOrHeading"}),new Te({OptionsClass:Kt,nameKey:"rules.yaml-title-alias.alias-helper-key.name",descriptionKey:"rules.yaml-title-alias.alias-helper-key.description",optionsKey:"aliasHelperKey"}),new V({OptionsClass:Kt,nameKey:"rules.yaml-title-alias.remove-alias-if-empty.name",descriptionKey:"rules.yaml-title-alias.remove-alias-if-empty.description",optionsKey:"removeAliasKeyWhenEmpty"})]}};zp=I(jE),Zi=O(zp,0,"YamlTitleAlias",vv,Zi),L(zp,1,Zi);var Av,wv,Ir;wv=[w.noSettingControl()],Av=[w.noSettingControl()];var Xi=class{constructor(){this.fileName=L(Ir,8,this),L(Ir,11,this);this.defaultEscapeCharacter=L(Ir,12,this,'"'),L(Ir,15,this);this.titleKey="title";this.mode="first-h1-or-filename-if-h1-missing"}};Ir=I(null),O(Ir,5,"fileName",wv,Xi),O(Ir,5,"defaultEscapeCharacter",Av,Xi),oe(Ir,Xi);var xv,qp,HE;xv=[w.register];var er=class extends(HE=w){constructor(){super({nameKey:"rules.yaml-title.name",descriptionKey:"rules.yaml-title.description",type:"YAML",hasSpecialExecutionOrder:!0})}get OptionsClass(){return Xi}apply(t,e,i){let r="";switch(e.mode){case"filename":r=e.fileName;break;case"first-h1":r=this.getFirstH1Header(t,i);break;default:r=this.getFirstH1Header(t,i),r=r||e.fileName}return r=nt(r,e.defaultEscapeCharacter),t=$t(t),Ee(t,s=>{let a=`
${e.titleKey}:.*
`,o=new RegExp(a);if(o.test(s))s=s.replace(o,ft(`
${e.titleKey}: ${r}
`));else{let l=s.indexOf(`
---`);s=Ia(s,l,`
${e.titleKey}: ${r}`)}return s})}getFirstH1Header(t,e){return yl(t,e.combinedWith([y.code,y.math,y.yaml,y.tag]))}get optionBuilders(){return[new Te({OptionsClass:Xi,nameKey:"rules.yaml-title.title-key.name",descriptionKey:"rules.yaml-title.title-key.description",optionsKey:"titleKey"}),new de({OptionsClass:Xi,nameKey:"rules.yaml-title.mode.name",descriptionKey:"rules.yaml-title.mode.description",optionsKey:"mode",records:[{value:"first-h1-or-filename-if-h1-missing",description:"Uses the first H1 in the file or the filename of the file if there is not H1"},{value:"filename",description:"Uses the filename as the title"},{value:"first-h1",description:"Uses the first H1 in the file as the title"}]})]}};qp=I(HE),er=O(qp,0,"YamlTitle",xv,er),L(qp,1,er);var $E=`<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-file-cog">
<circle cx="6" cy="13" r="3"/>
<path d="m9.7 14.4-.9-.3"/>
<path d="m3.2 11.9-.9-.3"/>
<path d="m4.6 16.7.3-.9"/>
<path d="m7.6 16.7-.4-1"/>
<path d="m4.8 10.3-.4-1"/>
<path d="m2.3 14.6 1-.4"/>
<path d="m8.7 11.8 1-.4"/>
<path d="m7.4 9.3-.3.9"/>
<path d="M14 2v6h6"/>
<path d="M4 5.5V4a2 2 0 0 1 2-2h8.5L20 7.5V20a2 2 0 0 1-2 2H6a2 2 0 0 1-2-1.5"/>
</svg>`,VE=`<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-folder-cog">
<circle cx="18" cy="18" r="3"/>
<path d="M10.5 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v3.5"/>
<path d="m21.7 19.4-.9-.3"/>
<path d="m15.2 16.9-.9-.3"/>
<path d="m16.6 21.7.3-.9"/>
<path d="m19.1 15.2.3-.9"/>
<path d="m19.6 21.7-.4-1"/>
<path d="m16.8 15.3-.4-1"/>
<path d="m14.3 19.6 1-.4"/>
<path d="m20.7 16.8 1-.4"/>
</svg>`,GE=`<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-server-cog">
<circle cx="12" cy="12" r="3"/><path d="M4.5 10H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-.5"/>
<path d="M4.5 14H4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2h-.5"/>
<path d="M6 6h.01"/><path d="M6 18h.01"/>
<path d="m15.7 13.4-.9-.3"/>
<path d="m9.2 10.9-.9-.3"/>
<path d="m10.6 15.7.3-.9"/>
<path d="m13.6 15.7-.4-1"/>
<path d="m10.8 9.3-.4-1"/>
<path d="m8.3 13.6 1-.4"/>
<path d="m14.7 10.8 1-.4"/>
<path d="m13.4 8.3-.3.9"/>
</svg>`,QE=`<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-file-x">
<path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/>
<path d="M14 2v4a2 2 0 0 0 2 2h4"/>
<path d="m14.5 12.5-5 5"/>
<path d="m9.5 12.5 5 5"/>
</svg>`,JE=`<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-folder-x">
<path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"/>
<path d="m9.5 10.5 5 5"/>
<path d="m14.5 10.5-5 5"/>
</svg>`,bt={folder:{id:"lint-folder",source:VE},ignoreFolder:{id:"lint-ignore-folder",source:JE},file:{id:"lint-file",source:$E},ignoreFile:{id:"lint-ignored-file",source:QE},vault:{id:"lint-vault",source:GE}};var pa=require("obsidian");var ZE=["move-footnotes-to-the-bottom","re-index-footnotes","line-break-at-document-end","file-name-heading","header-increment"],ed=class{constructor(){this.disabledRules=[]}lintText(t){this.skipFile=!1;let e=t.oldText;if([this.disabledRules,this.skipFile]=kc(e),this.skipFile)return e;sr(A("logs.rule-running"));let i=A("logs.pre-rules");sr(i);let r=this.runBeforeRegularRules(t);ai(i);let s=!1;for(let u of t.settings.ruleConfigs["auto-correct-common-misspellings"]["extra-auto-correct-files"]??[])if(u.filePath!=""){s=!0;break}let a=A("logs.disabled-text"),o={fileCreatedTime:t.fileInfo.createdAtFormatted,fileModifiedTime:t.fileInfo.modifiedAtFormatted,fileName:t.fileInfo.name,locale:t.momentLocale,minimumNumberOfDollarSignsToBeAMathBlock:t.settings.commonStyles.minimumNumberOfDollarSignsToBeAMathBlock,aliasArrayStyle:t.settings.commonStyles.aliasArrayStyle,tagArrayStyle:t.settings.commonStyles.tagArrayStyle,defaultArrayStyle:t.settings.commonStyles.defaultArrayStyle,defaultEscapeCharacter:t.settings.commonStyles.escapeCharacter,removeUnnecessaryEscapeCharsForMultiLineArrays:t.settings.commonStyles.removeUnnecessaryEscapeCharsForMultiLineArrays},l=[];for(let u of Dn){if(this.disabledRules.includes(u.alias)){$e(u.alias+" "+a);continue}else if(u.hasSpecialExecutionOrder||u.type==="Paste")continue;if(u.alias==="auto-correct-common-misspellings"&&s){let d=!1;for(let m of t.settings.ruleConfigs["auto-correct-common-misspellings"]["extra-auto-correct-files"]??[])if(m.filePath==t.fileInfo.path){d=!0;break}if(d){$e(u.alias+" "+a);continue}}l.push(u)}r=this.runRulesInBatches(l,r,t.settings,o);let c=A("logs.custom-regex");return sr(c),r=this.runCustomRegexReplacement(t.settings.customRegexes,r),ai(c),t.oldText=r,this.runAfterRegularRules(e,t)}runRulesInBatches(t,e,i,r){return this.runBatches(t,e,i,r,s=>s.type==="YAML"||ZE.includes(s.alias))}runBatches(t,e,i,r,s){let a=0;for(;a<t.length;){let o=e,l=on.for(o),c=[];for(;a<t.length;){let u=t[a];if(!u.getOptions(i)[u.enabledOptionName()]){a++;continue}let m=s(u);if(m&&c.length>0)break;let[p]=Ii.applyIfEnabledBase(u,o,i,r,l);if(p===o){a++;continue}if(!_h(c,Ue(o,p),o)||(a++,m))break}e=ke(o,c)}return e}runBeforeRegularRules(t){let e=t.oldText;return[e]=Pi.applyIfEnabled(e,t.settings,this.disabledRules),[e]=_i.applyIfEnabled(e,t.settings,this.disabledRules,{defaultEscapeCharacter:t.settings.commonStyles.escapeCharacter}),[e]=qi.applyIfEnabled(e,t.settings,this.disabledRules,{minimumNumberOfDollarSignsToBeAMathBlock:t.settings.commonStyles.minimumNumberOfDollarSignsToBeAMathBlock}),[e]=Ri.applyIfEnabled(e,t.settings,this.disabledRules,{misspellingToCorrection:t.defaultMisspellings}),[e]=zi.applyIfEnabled(e,t.settings,this.disabledRules,{defaultEscapeCharacter:t.settings.commonStyles.escapeCharacter,tagArrayStyle:t.settings.commonStyles.tagArrayStyle,aliasArrayStyle:t.settings.commonStyles.aliasArrayStyle,defaultArrayStyle:t.settings.commonStyles.defaultArrayStyle,removeUnnecessaryEscapeCharsForMultiLineArrays:t.settings.commonStyles.removeUnnecessaryEscapeCharsForMultiLineArrays}),e}runAfterRegularRules(t,e){let i=e.oldText,r=A("logs.post-rules");sr(r),[i]=Di.applyIfEnabled(i,e.settings,this.disabledRules),[i]=er.applyIfEnabled(i,e.settings,this.disabledRules,{fileName:e.fileInfo.name,defaultEscapeCharacter:e.settings.commonStyles.escapeCharacter}),[i]=Zi.applyIfEnabled(i,e.settings,this.disabledRules,{fileName:e.fileInfo.name,aliasArrayStyle:e.settings.commonStyles.aliasArrayStyle,defaultEscapeCharacter:e.settings.commonStyles.escapeCharacter,removeUnnecessaryEscapeCharsForMultiLineArrays:e.settings.commonStyles.removeUnnecessaryEscapeCharsForMultiLineArrays});let s=[Fi.getRule(),Ki.getRule(),Qi.getRule(),Yi.getRule()].filter(u=>this.disabledRules.includes(u.alias)?($e(u.alias+" "+A("logs.disabled-text")),!1):!0);i=this.runBatches(s,i,e.settings,{defaultEscapeCharacter:e.settings.commonStyles.escapeCharacter},()=>!1);let a=i.match(Ze);a!=null&&([i]=ti.applyIfEnabled(i,e.settings,this.disabledRules));let o=e.getCurrentTime(),l;[i,l]=zn.applyIfEnabled(i,e.settings,this.disabledRules,{fileCreatedTime:e.fileInfo.createdAtFormatted,fileModifiedTime:e.fileInfo.modifiedAtFormatted,currentTime:o,alreadyModified:t!=i,locale:e.momentLocale}),a===null&&([i]=ti.applyIfEnabled(i,e.settings,this.disabledRules));let c=zn.getRuleOptions(e.settings);return o=e.getCurrentTime(),c.convertToUTC&&(o=o.utc()),[i]=Ji.applyIfEnabled(i,e.settings,this.disabledRules,{currentTimeFormatted:o.format(c.format?.trimEnd()),yamlTimestampDateModifiedEnabled:l&&c.dateModified,dateModifiedKey:c.dateModifiedKey}),ai(r),ai(A("logs.rule-running")),i}runCustomCommands(t,e){if(this.skipFile)return;$e(A("logs.running-custom-lint-command"));let i=new Set;for(let r of t)if(!(!r.id||!r.enabLine truncated
`),l+=`/${s.find}/${s.flags}/${s.replace}/`,$e(l);let c=new RegExp(`${s.find}`,s.flags),u=on.for(i).protectedRangesFor([y.customIgnore]);i=Jf(i,c,Xf(s.replace),u),r!=i&&$e(i),r=i}return i}runPasteLint(t,e,i){let r=i.oldText;return[r]=Hi.applyIfEnabled(r,i.settings,[]),[r]=Gi.applyIfEnabled(r,i.settings,[]),[r]=Vi.applyIfEnabled(r,i.settings,[]),[r]=Ui.applyIfEnabled(r,i.settings,[]),[r]=$i.applyIfEnabled(r,i.settings,[]),[r]=Wi.applyIfEnabled(r,i.settings,[],{lineContent:t,selectedText:e}),[r]=ji.applyIfEnabled(r,i.settings,[],{lineContent:t,selectedText:e}),[r]=Bi.applyIfEnabled(r,i.settings,[],{lineContent:t}),r}runYAMLTimestampByItself(t){let e=t.oldText,i=t.getCurrentTime();return[e]=zn.applyIfEnabled(e,t.settings,this.disabledRules,{fileCreatedTime:t.fileInfo.createdAtFormatted,fileModifiedTime:t.fileInfo.modifiedAtFormatted,currentTime:i,alreadyModified:!0,locale:t.momentLocale}),e}};function tr(n,t=null,e,i,r){let s=t&&t.stat.ctime!==0?(0,pa.moment)(t.stat.ctime):(0,pa.moment)();s.locale(e);let a=t?(0,pa.moment)(t.stat.mtime):(0,pa.moment)();a.locale(e);let o=a.format(),l=s.format();return{oldText:n,fileInfo:{name:t?t.basename:"",createdAtFormatted:l,modifiedAtFormatted:o,path:t?t.path:""},settings:i,momentLocale:e,getCurrentTime:()=>{let c=(0,pa.moment)();return c.locale(e),c},defaultMisspellings:r}}var td=require("obsidian");var Co=class extends td.Modal{constructor(t,e,i,r,s,a=!1,o){super(t),this.modalEl.addClass("confirm-modal"),this.contentEl.createEl("h3",{text:A("warning-text"),cls:"modal-heading"}),a&&this.contentEl.createEl("p",{text:A("custom-command-warning"),cls:"modal-warn"}),this.contentEl.createEl("p",{text:e+" "+A("file-backup-text")}).id="confirm-dialog";let l;if(o){let c=this.contentEl.createDiv("confirm-modal-checkbox-container");l=c.createEl("input",{type:"checkbox",attr:{id:"suppress-confirmation"}}),c.createEl("label",{text:A("do-not-show-again"),attr:{for:"suppress-confirmation"}})}this.contentEl.createDiv("modal-button-container",c=>{c.createEl("button",{text:A("cancel-button-text")}).addEventListener("click",()=>this.close());let u=c.createEl("button",{attr:{type:"submit"},cls:"mod-cta",text:i});u.addEventListener("click",async d=>{o&&l?.checked&&await o(),new td.Notice(r),this.close(),await s()}),window.setTimeout(()=>{u.focus()},50)})}};var id=require("obsidian"),Lv=Sn(Bo());var Wp={YAML:"tabs.names.yaml",Heading:"tabs.names.heading",Footnote:"tabs.names.footnote",Content:"tabs.names.content",Spacing:"tabs.names.spacing",Paste:"tabs.names.paste",Custom:"tabs.names.custom",Debug:"tabs.names.debug"},XE=Object.keys(Lv.default.levels),nd=class extends id.PluginSettingTab{constructor(e,i){super(e,i);this.plugin=i}getControlValue(e){return af(this.plugin.settings,e)}async setControlValue(e,i){of(this.plugin.settings,e,i),await this.plugin.saveSettings()}getSettingDefinitions(){return[...this.generalDefinitions(),this.commonStylesGroup(),{type:"group",heading:A("tabs.general.files-and-folders"),items:[this.foldersToIgnorePage(),this.filesToIgnorePage(),this.additionalFileExtensionsPage()]},{type:"group",heading:A("tabs.general.rules"),items:Object.values(z).map(e=>this.rulePageFor(e))},this.customPage(),this.debugPage()]}generalDefinitions(){let e=this.plugin.settings,i=[];i.push({name:A("tabs.general.lint-on-save.name"),desc:fe(A("tabs.general.lint-on-save.description")),render:a=>{a.addToggle(o=>o.setValue(e.lintOnSave).onChange(async l=>{e.lintOnSave=l,await this.plugin.saveSettings(),this.refreshDomState()}))}}),i.push({name:A("tabs.general.display-message.name"),desc:fe(A("tabs.general.display-message.description")),visible:()=>e.lintOnSave,control:{type:"toggle",key:"displayChanged"}}),i.push({name:A("tabs.general.lint-on-file-change.name"),desc:fe(A("tabs.general.lint-on-file-change.description")),render:a=>{a.addToggle(o=>o.setValue(e.lintOnFileChange).onChange(async l=>{e.lintOnFileChange=l,await this.plugin.saveSettings(),this.refreshDomState()}))}}),i.push({name:A("tabs.general.display-lint-on-file-change-message.name"),desc:fe(A("tabs.general.display-lint-on-file-change-message.description")),visible:()=>e.lintOnFileChange,control:{type:"toggle",key:"displayLintOnFileChangeNotice"}}),i.push({name:A("tabs.general.suppress-message-when-no-change.name"),desc:fe(A("tabs.general.suppress-message-when-no-change.description")),control:{type:"toggle",key:"suppressMessageWhenNoChange"}}),i.push({name:A("tabs.general.enable-diff-preview-view.name"),desc:fe(A("tabs.general.enable-diff-preview-view.description")),control:{type:"toggle",key:"enableDiffPreviewView"}});let r=navigator.language?.toLowerCase(),s={"system-default":A("tabs.general.same-as-system-locale").replace("{SYS_LOCALE}",r)};for(let a of id.moment.locales())s[a]=a;return i.push({name:A("tabs.general.override-locale.name"),desc:fe(A("tabs.general.override-locale.description")),render:a=>{a.addDropdown(o=>{for(let[l,c]of Object.entries(s))o.addOption(l,c);o.setValue(e.linterLocale),o.onChange(async l=>{e.linterLocal Line truncated
`)),s.inputEl.addClass("linter-debug-readonly")})}}];return{type:"page",name:A(Wp.Debug),items:i}}};var Ev=require("obsidian");var eT=/^---\n/gm,Sv=`${ms}:`,rd=class extends Ev.EditorSuggest{constructor(e){super(e.app);this.plugin=e;this.inline=!1;let i=A("all-rules-option");this.ruleInfo=[{displayName:i,name:i.toLowerCase(),alias:"all"}];for(let r of Dn){let s=r.getName();this.ruleInfo.push({displayName:s,name:s.toLowerCase(),alias:r.alias})}}onTrigger(e,i,r){let s=i.getLine(e.line).toLowerCase();if(s.startsWith(Sv)||this.disabledRulesIsEndOfStartOfFileToCursor(i.getRange({line:0,ch:0},e))){this.inline=s.startsWith(Sv);let o=i.getLine(e.line).substring(0,e.ch),l=o.match(/(\S+)$/)?.first().replaceAll("[","").replaceAll("]","");if(l)return{end:e,start:{ch:o.lastIndexOf(l),line:e.line},query:l}}return null}getSuggestions(e){let[i,r]=kc(e.editor.getValue());if(r)return[];let s=e.query.toLowerCase();return this.ruleInfo.filter(o=>(o.name.contains(s)||o.alias.contains(s))&&!i.includes(o.alias))}renderSuggestion(e,i){i.addClass("mod-complex");let r=i.createDiv({cls:"suggestion-content"});r.createDiv({cls:"suggestion-title"}).setText(`${e.displayName}`),r.createDiv({cls:"suggestion-note"}).setText(`${e.alias}`)}selectSuggestion(e){if(this.context){let i=e.alias;this.inline?i=`${i},`:i=`${i}
-`,this.context.editor.replaceRange(`${i} `,this.context.start,this.context.end)}}disabledRulesIsEndOfStartOfFileToCursor(e){if(!e||!e.length||e.match(eT)?.length!=1)return!1;let i=Le(e+`
`,ms)?.trimEnd();return i===null?!1:e.trimEnd().endsWith(i)}};var Dv=Sn(Cv()),Yv=Sn(Bo());var Rr=require("obsidian");var Up="default-misspellings.md",jp=`https://raw.githubusercontent.com/platers/obsidian-linter/refs/heads/master/src/utils/${Up}`;async function Iv(n,t){let e=n.app,i=n.manifest.dir??"",r=(0,Rr.normalizePath)(i+"/"+Up);if(await e.vault.adapter.exists(r))return;let s=new Rr.Notice(A("rules.auto-correct-common-misspellings.default-install")),a=null;try{a=await(0,Rr.requestUrl)(jp)}catch(o){_o(A("rules.auto-correct-common-misspellings.default-install-failed").replace("{URL}",jp),o instanceof Error?o:new Error(String(o)))}if(!a||a.status!==200){let o=A("rules.auto-correct-common-misspellings.default-install-failed").replace("{URL}",jp)+A("logs.see-console");await t(o);return}await e.vault.adapter.exists(i)||await e.vault.adapter.mkdir(i),await e.vault.adapter.writeBinary(r,a.arrayBuffer),s.hide()}async function Rv(n){let t=n.app,e=n.manifest.dir??"",i=(0,Rr.normalizePath)(e+"/"+Up);return await t.vault.adapter.exists(i)?await t.vault.adapter.read(i):(Wt(A("rules.auto-correct-common-misspellings.defaults-missing").replace("{FILE}",i)),"")}var Fv=require("obsidian"),ri=Sn(Ka());var fa="linter-diff-preview",tT=3e5,Nv=3,sd=class extends Fv.ItemView{constructor(e){super(e);this.previewState=null;this.navigation=!1,this.icon="git-compare"}getViewType(){return fa}getDisplayText(){return A("notice-text.lint-preview-title")}async onOpen(){this.contentEl.empty(),this.contentEl.addClass("linter-diff-preview-view"),this.render()}setPreview(e){this.previewState=e,this.render()}render(){if(!this.contentEl)return;if(this.contentEl.empty(),this.contentEl.addClass("linter-diff-preview-view"),!this.previewState){this.contentEl.createDiv({cls:"linter-diff-preview-empty",text:A("notice-text.no-preview-changes")});return}let e=this.contentEl.createDiv("linter-diff-preview-header"),i=e.createDiv("linter-diff-preview-title-group");i.createEl("h3",{text:this.previewState.title});let r=this.previewState.oldText!==this.previewState.newText;r||i.createDiv({cls:"linter-diff-summary",text:A("notice-text.no-preview-changes")});let s=e.createDiv("linter-diff-preview-actions");if(s.createEl("button",{text:A("close-button-text")}).addEventListener("click",()=>{this.previewState=null,this.render()}),r&&s.createEl("button",{attr:{type:"submit"},cls:"mod-cta",text:A("notice-text.apply-lint-preview")}).addEventListener("click",()=>this.applyPreview()),this.bodyEl=this.contentEl.createDiv("linter-diff-preview-body"),!!r){if(this.previewState.oldText.length+this.previewState.newText.length>tT){this.bodyEl.createEl("p",{text:A("notice-text.diff-large-file-warning")}),this.bodyEl.createEl("button",{text:A("notice-text.show-diff")}).addEventListener("click",()=>this.renderDiff());return}this.renderDiff()}}applyPreview(){if(!this.previewState)return;let e=this.previewState;e.applyAction(),this.previewState={...e,oldText:e.newText},this.render()}renderDiff(){if(!this.previewState||!this.bodyEl)return;this.bodyEl.empty();let e=this.createLineDiff(this.previewState.oldText,this.previewState.newText),i=this.createSummary(e);this.bodyEl.createDiv({text:A("notice-text.diff-summary").replace("{LINES_ADDED}",i.linesAdded.toString()).replace("{LINES_REMOVED}",i.linesRemoved.toString()).replace("{CHARS_ADDED}",i.charsAdded.toString()).replace("{CHARS_REMOVED}",i.charsRemoved.toString()),cls:"linter-diff-summary"});let r=this.bodyEl.createDiv({cls:"linter-diff"});this.renderDiffLines(r,this.createVisibleDiffLines(this.expandDiffs(e)))}createLineDiff(e,i){let r=new ri.default.diff_match_patch,s=r.diff_linesToChars_(e,i),a=r.diff_main(s.chars1,s.chars2,!1);return r.diff_charsToLines_(a,s.lineArray),a}createSummary(e){return e.reduce((i,[r,s])=>(r===ri.default.DIFF_INSERT?(i.charsAdded+=s.length,i.linesAdded+=this.countLines(s)):r===ri.default.DIFF_DELETE&&(i.charsRemoved+=s.length,i.linesRemoved+=this.countLines(s)),i),{charsAdded:0,charsRemoved:0,linesAdded:0,linesRemoved:0})}countLines(e){if(e==="")return 0;let i=e.split(`
`);return i[i.length-1]===""&&i.pop(),i.length}expandDiffs(e){let i=[];for(let[r,s]of e){let a=s.split(`
`);a[a.length-1]===""&&a.pop();for(let o of a)i.push({operation:r,text:o})}return i}createVisibleDiffLines(e){let i=new Array(e.length).fill(!1);for(let a=0;a<e.length;a++){if(e[a].operation===ri.default.DIFF_EQUAL)continue;let o=Math.max(0,a-Nv),l=Math.min(e.length-1,a+Nv);for(let c=o;c<=l;c++)i[c]=!0}let r=[],s=0;for(let a=0;a<e.length;a++)i[a]?(s>0&&(r.push({skipped:s}),s=0),r.push(e[a])):s++;return s>0&&r.push({skipped:s}),r}renderDiffLines(e,i){for(let r of i){if("skipped"in r){e.createDiv({cls:"linter-diff-skip",text:A("notice-text.diff-skipped-lines").replace("{COUNT}",r.skipped.toString())});continue}let s=e.createDiv({cls:this.diffClass(r.operation)});s.createSpan({cls:"linter-diff-marker",text:this.diffPrefix(r.operation)}),s.createSpan({cls:"linter-diff-text",text:r.text})}}diffClass(e){return e===ri.default.DIFF_INSERT?"linter-diff-line linter-diff-added":e===ri.default.DIFF_DELETE?"linter-diff-line linter-diff-removed":"linter-diff-line linter-diff-context"}diffPrefix(e){return e===ri.default.DIFF_INSERT?"+ ":e===ri.default.DIFF_DELETE?"- ":" "}};var nT={en:"en-gb",zh:"zh-cn","zh-TW":"zh-tw",ru:"ru",ko:"ko",it:"it",id:"id",ro:"ro","pt-BR":"pt-br",cz:"cs",da:"da",de:"de",es:"es",fr:"fr",no:"nn",pl:"pl",pt:"pt",tr:"tr",hi:"hi",nl:"nl",ar:"ar",ja:"ja"},si=0,Bv="preview-lint-file",ld=class extends re.Plugin{constructor(){super(...arguments);this.eventRefs=[];this.isEnabled=!0;this.rulesRunner=new ed;this.overridePaste=!1;this.hasCustomCommands=!1;this.customCommandsLock=new Dv.default;this.originalSaveCallback=null;this.editorLintFiles=[];this.fileLintFiles=new Set;this.customCommandsCallback=null;this.currentlyOpeningSidebar=!1;this.activeFileChangeDebouncer=new Map;this.defaultAutoCorrectMisspellings=new Map;this.hasLoadedMisspellingFiles=!1;this.diffPreviewCommandsRegistered=!1;this.saveSettingsDebounce=(0,re.debounce)(async e=>{await this.saveData(e)},5e3)}async onload(){Vy(),qo((0,re.getLanguage)()),qt(A("logs.plugin-load")),this.isEnabled=!0;for(let e in bt){let i=bt[e];(0,re.addIcon)(i.id,i.source)}await this.loadSettings(),this.addCommands(),this.registerView(fa,e=>new sd(e)),this.updateDiffPreviewViewStatus(),this.registerEventsAndSaveCallback(),this.registerEditorSuggest(new rd(this)),this.settings.textAreaSettingsConvertedToListItemSettings||await this.moveTextAreaSettingsToListItemSettings()&&await this.saveSettings(),this.settings.settingsConvertedToConfigKeyValues&&!this.settings.defaultArrayStyleMovedToCommonStyles&&await this.moveDefaultArrayStyleToCommonStyles(),this.settingsTab=new nd(this.app,this),this.addSettingTab(this.settingsTab)}async onunload(){qt(A("logs.plugin-unload")),this.isEnabled=!1;for(let i of this.eventRefs)this.app.workspace.offref(i);let e=this.app.commands?.commands?.["editor:save-file"];e&&e.checkCallback&&this.originalSaveCallback&&(e.checkCallback=this.originalSaveCallback)}async loadSettings(){let e=await this.loadData();this.settings=Object.assign({},ov,e),typeof this.settings.suppressMessageWhenNoChange!="boolean"&&(this.settings.suppressMessageWhenNoChange=!1),typeof this.settings.enableDiffPreviewView!="boolean"&&(this.settings.enableDiffPreviewView=!0),typeof this.settings.logLevel=="number"&&(this.settings.logLevel=uf(this.settings.logLevel)),Po(this.settings.logLevel),await this.setOrUpdateMomentInstance(),this.updatePasteOverrideStatus(),this.updateHasCustomCommandStatus()}updateDiffPreviewViewStatus(){if(this.settings.enableDiffPreviewView){this.registerDiffPreviewCommands();return}this.removeDiffPreviewCommands(),this.app.workspace.detachLeavesOfType(fa)}async saveSettings(){this.hasLoadedMisspellingFiles||await this.loadAutoCorrectFiles(!1),this.saveSettingsDebounce(this.settings),this.updatePasteOverrideStatus(),this.updateHasCustomCommandStatus(),this.updateDiffPreviewViewStatus()}addCommands(){this.addCommand({id:"lint-file",name:A("commands.lint-file.name"),editorCheckCallback:(e,i,r)=>{if(e)return this.isMarkdownFile(r.file)&&i.cm!=null;this.runLinterEditor(i)},icon:bt.file.id}),this.addCommand({id:"lint-file-unless-ignored",name:A("commands.lint-file-unless-ignored.name"),editorCheckCallback:(e,i,r)=>{if(e)return this.isMarkdownFile(r.file);!this.shouldIgnoreFile(r.file)&&i.cm&&this.runLinterEditor(i)},icon:bt.file.id}),this.addCommand({id:"lint-all-files",name:A("commands.lint-all-files.name"),icon:bt.vault.id,callback:()=>{if(this.settings.suppressLintAllFilesConfirmationModal){this.runLinterAllFiles(this.app);return}let e=A("commands.lint-all-files.start-message"),i=A("commands.lint-all-files.submit-button-text"),r=A("commands.lint-all-files.submit-button-notice-text");new Co(this.app,e,i,r,()=>this.runLinterAllFiles(this.app),this.settings.lintCommands&&this.settings.lintCommands.length>0,async()=>{this.settings.suppressLintAllFilesConfirmationModal=!0,await this.saveSettings()}).open()}}),this.addCommand({id:"lint-all-files-in-folder",name:A("commands.lint-all-files-in-folder.name"),icon:bt.folder.id,editorCheckCallback:(e,i,r)=>{if Line truncated
`+r),new re.Notice(r),this.settings.ruleConfigs["auto-correct-common-misspellings"].enabled=!1,await this.saveSettings()}),!!this.settings.ruleConfigs["auto-correct-common-misspellings"].enabled)){this.defaultAutoCorrectMisspellings=Hr(ln(await Rv(this)));for(let r of this.settings.ruleConfigs["auto-correct-common-misspellings"]["extra-auto-correct-files"]??[])if(r.filePath!=""){let s=this.app.vault.getFileByPath((0,re.normalizePath)(r.filePath));s&&(r.customReplacements=Hr(ln(await this.app.vault.cachedRead(s))))}this.hasLoadedMisspellingFiles=!0}}onMenuOpenCallback(e,i,r){i instanceof re.TFile&&this.isMarkdownFile(i)?this.shouldIgnoreFile(i)||(e.addItem(s=>{s.setIcon(bt.file.id).setTitle(A("commands.lint-file-pop-up-menu-text.name")).onClick(()=>{let a=this.app.workspace.getActiveFile(),o=this.getEditor();a===i&&o&&o.cm?this.runLinterEditor(o):this.runLinterFile(i)})}),e.addItem(s=>{s.setIcon(bt.ignoreFile.id).setTitle(A("commands.ignore-file-pop-up-menu-text.name")).onClick(()=>{this.addFileToIgnoreList(i)})})):i instanceof re.TFolder&&(this.settings.foldersToIgnore.includes(i.path)||(e.addItem(s=>{s.setTitle(A("commands.lint-folder-pop-up-menu-text.name")).setIcon(bt.folder.id).onClick(()=>this.createFolderLintModal(i))}),e.addItem(s=>{s.setTitle(A("commands.ignore-folder-pop-up-menu-text.name")).setIcon(bt.ignoreFolder.id).onClick(()=>{this.addFolderToIgnoreList(i)})})))}async onActiveLeafChange(){if(!this.isEnabled||this.currentlyOpeningSidebar)return;let e=this.app.workspace.getActiveFile(),i=this.lastActiveFile==null?!1:await this.app.vault.adapter.exists(this.lastActiveFile.path);if(!this.settings.lintOnFileChange||!i||this.lastActiveFile===e||!this.isMarkdownFile(this.lastActiveFile)||this.shouldIgnoreFile(this.lastActiveFile)){this.lastActiveFile=e;return}try{await this.runLinterFile(this.lastActiveFile,!0)}catch(r){this.handleLintError(this.lastActiveFile,r instanceof Error?r:new Error(String(r)),A("commands.lint-file.error-message")+" '{FILE_PATH}'",!1)}finally{this.lastActiveFile=e}}shouldIgnoreFile(e){for(let i of this.settings.foldersToIgnore)if(i.length>0&&e.path.startsWith((0,re.normalizePath)(i)+"/"))return!0;for(let i of this.settings.filesToIgnore){if(!i.match)continue;if(new RegExp(`${i.match}`,i.flags).test(e.path))return!0}return!1}isMarkdownFile(e){return e&&(e.extension==="md"||this.settings.additionalFileExtensions.includes(e.extension))}async runLinterFile(e,i=!1){let r=ln(await this.app.vault.read(e)),s=this.rulesRunner.lintText(tr(r,e,this.momentLocale,this.settings,this.defaultAutoCorrectMisspellings));if(r!=s){if(await this.app.vault.modify(e,s),i){let a=A("logs.file-change-lint-message-start")+" "+this.lastActiveFile.path;this.settings.displayLintOnFileChangeNotice&&new re.Notice(a),qt(a)}this.fileLintFiles.add(e);return}await this.runCustomCommandsInSidebar(e)}async runLinterAllFiles(e){let i=0;if(await Promise.all(e.vault.getMarkdownFiles().map(async r=>{if(!this.shouldIgnoreFile(r))try{await this.runLinterFile(r)}catch(s){this.handleLintError(r,s instanceof Error?s:new Error(String(s)),A("commands.lint-all-files.error-message")+" '{FILE_PATH}'"),i+=1}})),i===0)new re.Notice(A("commands.lint-all-files.success-message"),si);else{let r=i===1?A("commands.lint-all-files.errors-message-singular"):A("commands.lint-all-files.errors-message-plural").replace("{NUM}",i.toString());new re.Notice(r,si)}}async runLinterAllFilesInFolder(e){qt(A("logs.folder-lint")+e.name);let i=0,r=0,s=this.getAllFilesInFolder(e);if(await Promise.all(s.map(async a=>{if(!this.shouldIgnoreFile(a)){try{await this.runLinterFile(a)}catch(o){this.handleLintError(a,o instanceof Error?o:new Error(String(o)),A("commands.lint-all-files-in-folder.error-message")+" '{FILE_PATH}'"),i+=1}r++}})),i===0)new re.Notice(A("commands.lint-all-files-in-folder.success-message").replace("{NUM}",r.toString()).replace("{FOLDER_NAME}",e.name),si);else{let a=i===1?A("commands.lint-all-files-in-folder.message-singular").replace("{NUM}",r.toString()).replace("{FOLDER_NAME}",e.name):A("commands.lint-all-files-in-folder.message-plural").replace("{FILE_COUNT}",r.toString()).replace("{FOLDER_NAME}",e.name).replace("{ERROR_COUNT}",i.toString());new re.Notice(a,si)}}createFolderLintModal(e){if(this.settings.suppressLintAllFilesInFolderConfirmationModal){this.runLinterAllFilesInFolder(e);return}let i=A("commands.lint-all-files-in-folder.start-message").replace("{FOLDER_NAME}",e.name),r=A("commands.lint-all-files-in-folder.submit-button-text").replace("{FOLDER_NAME}",e.name),s=A("commands.lint-all-files-in-folder.submit-button-notice-text").replace("{FOLDER_NAME}",e.name);new Co(this.app,i,r,s,()=>this.runLinterAllFilesInFolder(e),this.settings.lintCommands&&this.settings.lintCommands.length>0,async()=>{this.settings.suppressLintAllFilesInFolderConfirmationModal=!0,await this.saveSettings()}).open()}async runLinterEditor(e){Yr(this.settings.recordLintOnSaveLogs),fd(),qt(A("logs.linter-run"));let i=this.app.workspace.getActiveFile(),r=ln(e. Line truncated
`+A("disabled-conflicting-rule-notice").replace("{NAME_1}",A("rules.header-increment.start-at-h2.name")).replace("{NAME_2}",A("rules.file-name-heading.name"))),this.settings.ruleConfigs["paragraph-blank-lines"]&&this.settings.ruleConfigs["paragraph-blank-lines"].enabled&&this.settings.ruleConfigs["two-spaces-between-lines-with-content"]&&this.settings.ruleConfigs["two-spaces-between-lines-with-content"].enabled&&(this.settings.ruleConfigs["paragraph-blank-lines"].enabled=!1,e=!0,r&&(i+=`
`),r=!0,i+=`
`+A("disabled-conflicting-rule-notice").replace("{NAME_1}",A("rules.paragraph-blank-lines.name")).replace("{NAME_2}",A("rules.two-spaces-between-lines-with-content.name"))),r&&new re.Notice(i,si);for(let s of Dn){let a=s.getDefaultOptions();if(!this.settings.ruleConfigs[s.alias]){this.settings.ruleConfigs[s.alias]=a,e=!0;continue}for(let o of Object.keys(a))Object.hasOwn(this.settings.ruleConfigs[s.alias],o)||(this.settings.ruleConfigs[s.alias][o]=a[o],e=!0)}for(let s of this.settings.customRegexes)Object.hasOwn(s,"enabled")||(s.enabled=!0,e=!0);for(let s of this.settings.lintCommands)Object.hasOwn(s,"enabled")||(s.enabled=!0,e=!0);e&&await this.saveSettings()}createDebouncedFileUpdate(){let e=5e3;switch(this.settings.ruleConfigs["yaml-timestamp"]["update-on-file-contents-updated"]??"never"){case"after 10 seconds":e=1e4;break;case"after 15 seconds":e=15e3;break;case"after 30 seconds":e=3e4;break;case"after 1 minute":e=6e4;break}return(0,re.debounce)(async(i,r)=>{if(!this.activeFileChangeDebouncer.has(i.path)){Wt(A("logs.file-change-yaml-lint-warning"));return}let s=this.activeFileChangeDebouncer.get(i.path);s.isRunning=!0;let a=ln(r.getValue()),o=ln(await this.app.vault.cachedRead(i)),l=a===o,c="";if(l){c=a;let u;if(c!=s.originalText){qt(A("logs.file-change-yaml-lint-run"));try{u=this.rulesRunner.runYAMLTimestampByItself(tr(c,i,this.momentLocale,this.settings,null))}catch(d){this.handleLintError(i,d instanceof Error?d:new Error(String(d)),A("commands.lint-file.error-message")+" '{FILE_PATH}'",!1);return}s.markdownInfo instanceof re.MarkdownView&&(s.markdownInfo.getState().mode==="source"?this.updateEditor(c,u,r):await this.app.vault.process(i,()=>u))}else qt(A("logs.file-change-yaml-lint-skipped"))}else c=o,c!=s.originalText?(qt(A("logs.file-change-yaml-lint-run")),await this.app.vault.process(i,u=>{qt(A("logs.file-change-yaml-lint-run"));try{return this.rulesRunner.runYAMLTimestampByItself(tr(c,i,this.momentLocale,this.settings,null))}catch(d){return this.handleLintError(i,d instanceof Error?d:new Error(String(d)),A("commands.lint-file.error-message")+" '{FILE_PATH}'",!1),u}})):qt(A("logs.file-change-yaml-lint-skipped"));this.activeFileChangeDebouncer.delete(i.path),s.isRunning=!1},e,!0)}updateEditor(e,i,r){let a=new ad.default.diff_match_patch().diff_main(e,i),o=r.cm.state.doc.length;if(e.length!==o)r.cm.dispatch({changes:{from:0,to:o,insert:i},filter:!1});else{let l=Qy(a);l.length>0&&r.cm.dispatch({changes:l,filter:!1})}return a}displayChangedMessage(e,i){let r=this.settings.suppressMessageWhenNoChange??!1;if(this.settings.displayChanged){if(r&&e+i===0)return;let s=Gy`
${e} ${A("notice-text.characters-added")}
${i} ${A("notice-text.characters-removed")}
`;new re.Notice(s)}}handleLintError(e,i,r,s=!0){let a=r.replace("{FILE_PATH}",e.path),o=A("logs.see-console");i instanceof fs?s?new re.Notice(`${a} ${i.message}.
${o}`,si):new re.Notice(`${i.message}.
${o}`,si):new re.Notice(`${A("logs.unknown-error")} ${o}`,si),_o(a,i)}async modifyPasteEvent(e,i){if(!i)return;let r=e.clipboardData.getData("text/plain");if(!r)return;let s=r.trim();if(Jr.lastIndex=0,Jr.test(s)){Wt(A("logs.paste-link-warning"));return}if(e.stopPropagation(),e.preventDefault(),!e.defaultPrevented)return;let a=this.app.vault.getConfig("autoConvertHtml"),o=e.clipboardData.getData("text/html"),l=o&&a&&o.indexOf("<!-- obsidian -->")===-1?(0,re.htmlToMarkdown)(o):r,c=i.listSelections();if(c.length===1){let u=c[0];l=this.rulesRunner.runPasteLint(this.getLineContent(i,u),i.getSelection()??"",tr(l,null,this.momentLocale,this.settings,null)),i.replaceSelection(l)}else this.handleMultiCursorPaste(i,c,l)}handleMultiCursorPaste(e,i,r){let s=this.convertContentIntoProperPasteContent(i,r),a=[];i.forEach((o,l)=>{r=this.rulesRunner.runPasteLint(this.getLineContent(e,o),e.getRange(o.anchor,o.head)??"",tr(s[l],null,this.momentLocale,this.settings,null)),a.push({text:r,from:o.anchor,to:o.head})}),e.transaction({changes:a})}convertContentIntoProperPasteContent(e,i){let r=i.split(`
`),s=[];if(r.length%e.length!==0)for(let a=0;a<e.length;a++)s.push(i);else{let a=r.length/e.length,o="";for(let l=0;l<r.length;l++)o+=r[l],(l+1===e.length||(l+1)%a===0)&&(s.push(o),o="")}return s}async pasteAsPlainText(e){let i=await navigator.clipboard.readText();if(!i){new re.Notice(A("notice-text.empty-clipboard"),si);return}e.replaceSelection(i)}setCustomCommandCallback(e){(0,Yv.warn)(A("logs.custom-command-callback-warning")),this.customCommandsCallback=e}async runCustomCommandsInSidebar(e){if(!this.settings.lintCommands||this.settings.lintCommands.length==0||!this.hasCustomCommands)return;let i=this.app.workspace.getRightLeaf(!1),r=this.getEditor();await this.customCommandsLock.acquire("command",async()=>{this.currentlyOpeningSidebar=!0,await i.openFile(e,{active:!0}),this.rulesRunner.runCustomCommands(this.settings.lintCommands,this.app.commands),this.customCommandsCallback&&await this.customCommandsCallback(e)}),i.detach(),r&&r.focus(),this.currentlyOpeningSidebar=!1}async runCustomCommands(e){!this.settings.lintCommands||this.settings.lintCommands.length==0||!this.hasCustomCommands||await this.customCommandsLock.acquire("command",async()=>{try{this.rulesRunner.runCustomCommands(this.settings.lintCommands,this.app.commands)}catch(i){this.handleLintError(e,i instanceof Error?i:new Error(String(i)),A("commands.lint-file.error-message")+" '{FILE_PATH}'",!1)}this.customCommandsCallback&&await this.customCommandsCallback(e)})}getEditor(){let e=this.app.workspace.getActiveViewOfType(re.MarkdownView);return e?e.editor:null}getLineContent(e,i){return e.getLine(i.anchor.line)}async moveConfigValuesToKeyBasedFormat(){qo("en");let e=!1;for(let i of Dn){let r=A("rules."+i.alias+".name"),s=this.settings.ruleConfigs[r];if(s!=null){let a=A("rules."+i.alias+".description"),o={enabled:s[a]??!1};for(let l of i.options){if(l.configKey==="enabled")continue;let c=A("rules."+i.alias+"."+l.configKey+".name");o[l.configKey]=s[c]??l.defaultValue}this.settings.ruleConfigs[i.alias]=o,delete this.settings.ruleConfigs[r],e=!0}}return this.settings.settingsConvertedToConfigKeyValues=!0,await this.saveSettings(),qo((0,re.getLanguage)()),e}async moveTextAreaSettingsToListItemSettings(){let e=/\n/,i=[{ruleName:"auto-correct-common-misspellings",key:"ignore-words",splitter:qa},{ruleName:"capitalize-headings",key:"ignore-words",splitter:qa},{ruleName:"capitalize-headings",key:"lowercase-words",splitter:qa},{ruleName:"dedupe-yaml-array-values",key:"ignore-keys",splitter:qa},{ruleName:"force-yaml-escape",key:"force-yaml-escape-keys",splitter:e},{ruleName:"format-yaml-array",key:"force-multi-line-array-style",splitter:e},{ruleName:"format-yaml-array",key:"force-single-line-array-style",splitter:e},{ruleName:"insert-yaml-attributes",key:"text-to-insert",splitter:e},{ruleName:"move-tags-to-yaml",key:"tags-to-ignore",splitter:e},{ruleName:"remove-yaml-keys",key:"yaml-keys-to-remove",splitter:e},{ruleName:"sort-yaml-array-values",key:"ignore-keys",splitter:e},{ruleName:"sort-yaml-array-values",key:"ignore-keys",splitter:e},{ruleName:"yaml-key-sort",key:"yaml-key-priority-sort-order",splitter:e}],r=!1;for(let s of i){let a=this.settings.ruleConfigs[s.ruleName];if(!a)continue;let o=a[s.key];if(a!=null&&typeof o=="string"){let l=o.split(s.splitter);this.settings.ruleConfigs[s.ruleName][s.key]=l.length===1&&l[0].trim()===""?[]:l,r=!0}}return this.settings.textAreaSettingsConvertedToListItemSettings=!0,await this.saveSettings(),r}async moveDefaultArrayStyleToCommonStyles(){let e=lv(this.settings);return this.settings.defaultArrayStyleMovedToCommonStyles=!0,await this.saveSettings(),e}getAllFilesInFolder(e){let i=[],r=[e];for(let s of r)for(let a of s.children)a instanceof re.TFile&&this.isMarkdownFile(a)?i.push(a):a instanceof re.TFolder&&r.push(a);return i}updatePasteOverrideStatus(){for(let e of Er.get("Paste"))if(e.getOptions(this.settings)?.enabled){this.overridePaste=!0;return}this.overridePaste=!1}updateHasCustomCommandStatus(){for(let e of this.settings.lintCommands)if(e.id&&e.id.trim()!=""&&e.enabled){this.hasCustomCommands=!0;return}this.hasCustomCommands=!1}updateFileDebouncerText(e,i){this.activeFileChangeDebouncer.has(e.path)&&(this.activeFileChangeDebouncer.get(e.path).originalText=i)}async addFileToIgnoreList(e){this.settings.filesToIgnore.push({match:"^"+Mt(e.path)+"$",flags:"",label:""}),await this.saveSettings()}async addFolderToIgnoreList(e){this.settings.foldersToIgnore.push(e.path),await this.saveSettings()}};
/* nosourcemap */
+11
View File
@@ -0,0 +1,11 @@
{
"id": "obsidian-linter",
"name": "Linter",
"version": "1.34.1",
"minAppVersion": "1.13.0",
"description": "Formats and styles your notes. It can be used to format YAML tags, aliases, arrays, and metadata; footnotes; headings; spacing; math blocks; regular markdown contents like list, italics, and bold styles; and more with the use of custom rule options as well.",
"author": "Victor Tao",
"authorUrl": "https://github.com/platers",
"helpUrl": "https://platers.github.io/obsidian-linter/",
"isDesktopOnly": false
}
+1
View File
@@ -0,0 +1 @@
.linter-no-border{border:none}.linter-border-bottom{border-bottom:1px solid var(--background-modifier-border);border-top:0;margin-bottom:.75em}.custom-row-description{margin-top:0}.modal-warn,.search-zero-state{font-weight:700}.modal-heading,.search-zero-state{text-align:center}.confirm-modal-checkbox-container{align-items:center;display:flex;gap:6px;margin-top:8px}.disabled-list-entry{color:var(--text-faint)}.linter-diff-preview-view{display:flex;flex-direction:column;height:100%;min-width:0;overflow:hidden}.linter-diff-preview-empty{color:var(--text-muted);padding:16px}.linter-diff-preview-header{align-items:flex-start;border-bottom:1px solid var(--background-modifier-border);display:flex;flex:0 0 auto;gap:12px;justify-content:space-between;padding:12px 14px}.linter-diff-preview-title-group{min-width:0}.linter-diff-preview-header h3{font-size:var(--font-ui-medium);line-height:1.3;margin:0 0 6px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.linter-diff-preview-actions{display:flex;flex:0 0 auto;gap:8px}.linter-diff-preview-body{flex:1 1 auto;min-height:0;overflow:auto;padding:12px 14px 16px}.linter-diff-preview-view .linter-diff-summary{color:var(--text-normal);display:inline-block;font-size:var(--font-ui-small);margin:0 0 10px;padding:5px 8px}.linter-diff-preview-view .linter-diff,.linter-diff-preview-view .linter-diff-summary{background:var(--background-secondary);border:1px solid var(--background-modifier-border);border-radius:6px}.linter-diff-preview-view .linter-diff{font-family:var(--font-monospace);font-size:var(--font-smaller);line-height:1.45;margin:0;overflow:hidden;padding:6px 0}.linter-diff-preview-view .linter-diff-line{display:grid;grid-template-columns:26px minmax(0,1fr);min-height:20px;padding:1px 10px 1px 0}.linter-diff-preview-view .linter-diff-marker{color:var(--text-muted);padding-right:8px;text-align:right;user-select:none}.linter-diff-preview-view .linter-diff-text{min-width:0;overflow-wrap:anywhere;white-space:pre-wrap}.linter-diff-preview-view .linter-diff-skip{border-bottom:1px solid var(--background-modifier-border);border-top:1px solid var(--background-modifier-border);color:var(--text-faint);font-family:var(--font-interface);font-size:var(--font-ui-smaller);padding:4px 12px;text-align:center}.linter-diff-preview-view .linter-diff-added{background:rgba(var(--color-green-rgb),.12);color:var(--text-normal)}.linter-diff-preview-view .linter-diff-removed{background:rgba(var(--color-red-rgb),.12);color:var(--text-normal)}.linter-diff-preview-view .linter-diff-context{color:var(--text-muted)}
+33 -47
View File
@@ -4,21 +4,21 @@
"type": "split", "type": "split",
"children": [ "children": [
{ {
"id": "6d9088d392cb8604", "id": "880908ac22302761",
"type": "tabs", "type": "tabs",
"children": [ "children": [
{ {
"id": "22a4c1f201a1b00e", "id": "10ea163afc7dbc62",
"type": "leaf", "type": "leaf",
"state": { "state": {
"type": "markdown", "type": "markdown",
"state": { "state": {
"file": "00 INBOX/ai/valheim-items.md", "file": "TODO.md",
"mode": "preview", "mode": "source",
"source": true "source": true
}, },
"icon": "lucide-file", "icon": "lucide-file",
"title": "valheim-items" "title": "TODO"
} }
} }
] ]
@@ -91,7 +91,7 @@
"state": { "state": {
"type": "localgraph", "type": "localgraph",
"state": { "state": {
"file": "00 INBOX/ai/valheim-items.md", "file": "TODO.md",
"options": { "options": {
"collapse-filter": true, "collapse-filter": true,
"search": "", "search": "",
@@ -115,7 +115,7 @@
"linkStrength": 1, "linkStrength": 1,
"linkDistance": 250, "linkDistance": 250,
"scale": 0.6666666666666666, "scale": 0.6666666666666666,
"close": true "close": false
} }
}, },
"icon": "lucide-git-fork", "icon": "lucide-git-fork",
@@ -184,20 +184,6 @@
"title": "tag" "title": "tag"
} }
}, },
{
"id": "8918bf52a32e4a8e",
"type": "leaf",
"state": {
"type": "all-properties",
"state": {
"sortOrder": "frequency",
"showSearch": false,
"searchQuery": ""
},
"icon": "lucide-ghost",
"title": "all-properties"
}
},
{ {
"id": "c10908b3bd97f5fa", "id": "c10908b3bd97f5fa",
"type": "leaf", "type": "leaf",
@@ -231,43 +217,43 @@
"table-editor-obsidian:Advanced Tables Toolbar": false "table-editor-obsidian:Advanced Tables Toolbar": false
} }
}, },
"active": "22a4c1f201a1b00e", "active": "10ea163afc7dbc62",
"lastOpenFiles": [ "lastOpenFiles": [
"00 INBOX/ai/hyprland-lua-migration-plan.md", "00 INBOX/ai/adguard-pikachu-migration-design-tree.md",
"00 INBOX/ai/deadnix-architecture.md", "00 INBOX/ai/caps-escape-design.md",
"00 INBOX/ai/valheim-items.md", "03 wrk/tasks/0016-romm-manual-rom-migration.md",
"03 wrk/tasks/0015-romm-5-4-package.md",
"00 INBOX/ai/retroarch-zeus-design-tree.md",
"TODO.md", "TODO.md",
"00 INBOX/ai/romm-5-4-deployment-changes-design-tree.md",
"00 INBOX/ai/romm-migration-design-tree.md",
"00 INBOX/ai/romm-5-4-package-design-tree.md",
"00 INBOX/ai/steamvr-quest-3-design-tree.md",
"AGENTS.md", "AGENTS.md",
"03 wrk/homelab.md",
"00 INBOX/ai/nixos-agents-style-scope-design-tree.md",
"03 wrk/tasks/0014-romm-guest.md",
"00 INBOX/ai/tldr-design-tree.md",
"00 INBOX/ai/tldr-design.md",
"00 INBOX/ai/valheim-items.md",
"03 wrk/tasks/0013-oidc-provider.md",
"03 wrk/tasks/0002-nixos-refactor.md",
"03 wrk/tasks/0011-gitea-axi-rust-migration.md",
"00 INBOX/credits.md",
"00 INBOX/ai/grill-skill-design.md",
"03 wrk/tasks/0012-gitea-axi-pr-merge-guardrail.md",
"00 INBOX/ai/gitea-axi-pr-merge-guardrail.md",
"00 INBOX/ai/gitea-axi-rust-migration.md",
"00 INBOX/valheim progression.md", "00 INBOX/valheim progression.md",
"technical-writing.md", "03 wrk/tasks",
"rust-module-prototype.md",
"00 INBOX/ai/statix-architecture.md",
"00 INBOX/ai/nix-statix-deadnix-rules.md",
"00 INBOX/let order name resolution.md~", "00 INBOX/let order name resolution.md~",
"00 INBOX/nix name resolution.md",
"00 INBOX/let order name resolution.md",
"00 INBOX/nix name resolution.md~", "00 INBOX/nix name resolution.md~",
"TODO.md~", "TODO.md~",
"00 INBOX/ai/xatu-rule-implementation-order.md",
"00 INBOX/ai/xatu-architecture-design.md",
"00 INBOX/ai/nix-style-linter-plan.md",
"00 INBOX/ai/nix-style-guide-agent-customization.md",
"00 INBOX/ai/game-guest-readiness-plan.md",
"00 INBOX/ai/xatu-node-rule-static-dispatch-plan.md",
"00 INBOX/ai/nix-style-linter-pr-1-vendor-rnix.md",
"00 INBOX/ai/nix-style-linter-pr-3-let-order.md",
"00 INBOX/ai/nix-style-linter-pr-2-scaffold-cli.md",
"00 INBOX/ai/homepage-pikachu-setup-plan.md",
"00 INBOX/ai/source-driven-remote-deploy-plan.md",
"00 INBOX/ai/monorepo-work-report.md",
"00 INBOX/ai/clew-ast-exploration.md",
"00 INBOX/ai/steamcmd servers.md",
"00 INBOX/ai/clew-ast-exploration.md~", "00 INBOX/ai/clew-ast-exploration.md~",
"03 wrk/machoke.md~", "03 wrk/machoke.md~",
"03 wrk/falinks.md~", "03 wrk/falinks.md~",
"99 meta/attachments/bases/unlinked mentions.base", "99 meta/attachments/bases/unlinked mentions.base",
"00 INBOX/ai", "00 INBOX/ai",
"03 wrk/ai", "03 wrk/ai"
"99 meta/Untitled"
] ]
} }
@@ -0,0 +1,110 @@
# AdGuard migration to Pikachu: design tree
## Research facts
- The pinned Nixpkgs revision provides `adguardhome` version `0.107.79`.
- NixOS provides the `services.adguardhome` module.
- The module runs AdGuard Home as a hardened dynamic systemd user.
- It stores state in `/var/lib/AdGuardHome`.
- It grants `CAP_NET_BIND_SERVICE` for DNS port 53.
- It grants `CAP_NET_RAW` when AdGuard Home DHCP is enabled.
- The module supports an arbitrary YAML configuration through `settings`.
- The module supports fully declarative operation with `mutableSettings = false`.
- In fully declarative operation, the module replaces `/var/lib/AdGuardHome/AdGuardHome.yaml` on each service start.
- Fully declarative operation requires `dns.bootstrap_dns` as a list.
- Declarative settings pass an AdGuard configuration check during the build.
- `mutableSettings = true` merges declared settings into UI changes at service start.
- `mutableSettings = false` replaces the state configuration on every service start.
- `openFirewall` opens only the web interface port.
- The migration must explicitly open DNS ports 53/TCP and 53/UDP when clients need them.
- Pikachu has address `10.23.10.102` on its untagged network.
- Pikachu carries VLAN 20 and creates bridge `br-vlan20`.
- The guest framework runs each guest in its own systemd-nspawn container.
- Each guest attaches to a host VLAN bridge and receives an address through DHCP.
- Pikachu currently configures only VLAN 20 for guests.
- The repository has no AdGuard configuration, Proxmox inventory, or DHCP-provider configuration.
- The current DHCP provider remains unestablished.
- The current Proxmox AdGuard container uses MAC `bc:24:11:91:60:bf`.
- The current Proxmox AdGuard container uses address `10.23.20.33` on VLAN 20.
- This environment has no Proxmox SSH target or local Proxmox control utility.
- The current AdGuard configuration listens on all guest addresses at DNS port 53.
- The current AdGuard configuration has no allowed-client or disallowed-client restrictions.
- The current AdGuard configuration uses Cloudflare, Google, and Quad9 encrypted upstreams in parallel.
- The current AdGuard configuration disables DNSSEC.
- The current AdGuard configuration defines three local rewrites.
- The repository configures no host backup system or monitoring system.
- Hosts update through explicit `nixos-rebuild switch --flake` commands.
- The working tree has unrelated operator changes.
## Service tradeoffs
| Service | NixOS support | Domain filtering | Administration UI | DHCP | Encrypted DNS | Main tradeoff |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| AdGuard Home | `services.adguardhome`; checked YAML and mutable or immutable state | Native block lists, rules, and per-client policy | Native | Native | Upstream and client-facing encrypted DNS | Direct migration with the closest state and feature match. UI state conflicts with fully declarative operation unless configuration is immutable. |
| Blocky | `services.blocky`; checked declarative YAML | Native lists, allow lists, rewrites, and per-client groups | No UI; REST API and metrics only | No | Encrypted upstreams and client-facing DoH, DoT, and DoQ | Strong Git-managed configuration and low operational surface. It lacks an interactive administration interface and DHCP. |
| Pi-hole | `services.pihole-ftl` plus `services.pihole-web`; declarative TOML, lists, and dashboard | Native gravity lists, allow lists, regex rules, and groups | Native | Native | Use a companion for encrypted upstream DNS | Familiar filtering product with a dashboard. The migration changes product data and uses more coupled services. |
| Technitium DNS Server | `services.technitium-dns-server`; service and firewall options only | Native block lists and DNS applications | Native | Native | Upstream and client-facing encrypted DNS | Broadest DNS feature set, including authoritative DNS. NixOS does not expose its runtime configuration declaratively. |
| Unbound | `services.unbound`; structured server and free-form settings | Local zones or response-policy zones require custom policy management | No | No | DNS-over-TLS support | Mature validating recursive resolver. Filtering and user operations require separate design. |
| dnscrypt-proxy | `services.dnscrypt-proxy`; declarative TOML | Local block and allow rules, without a list-management UI | No | No | Encrypted upstream DNS, including DNSCrypt and DoH | Strong upstream privacy and resolver selection. It is not a full network filtering appliance. |
| Knot Resolver | `services.kresd`; structured listener settings and extra Lua | Custom policy modules | No | No | Client-facing DoH and TLS listeners | Flexible high-performance recursive resolver. Filtering requires resolver expertise and custom policy. |
| SmartDNS | `services.smartdns`; free-form settings | Domain and address rules | No NixOS-integrated UI | No | Encrypted upstream and client-facing DNS | Optimizes upstream selection and latency. It offers less complete filtering management than dedicated blockers. |
`Native` means that the product provides the feature without a companion service.
## Decision tree
- **D1 — DNS service product** [settled]
- Retain AdGuard Home on Pikachu.
- Constraint: Preserve AdGuard Home as the DNS service product.
- **D2A — AdGuard Home role** [settled]
- Provides DNS filtering and resolution only.
- Constraint: The existing DHCP provider continues to assign addresses and DHCP options.
- **D3A — Execution placement** [settled]
- Runs in a dedicated guest on Pikachu's existing VLAN 20.
- Constraint: Isolate AdGuard Home from the Pikachu host.
- **D4A — Guest network identity** [settled]
- Reuses MAC `bc:24:11:91:60:bf` and address `10.23.20.33` on VLAN 20.
- Constraint: Stop the Proxmox container before the guest starts.
- **D5A — Network exposure** [settled]
- Listens on all guest addresses at port 53.
- Accepts requests from every reachable internal device.
- **D6A — Resolver policy** [settled]
- Preserves the existing upstream resolvers and parallel resolver mode.
- Preserves disabled DNSSEC and the three local rewrites.
- **D7A — Configuration authority** [settled]
- Uses fully declarative Nix configuration.
- Constraint: Set `services.adguardhome.mutableSettings = false`.
- Constraint: Declare `dns.bootstrap_dns` as a list.
- Constraint: Web UI changes do not persist.
- Constraint: Match existing service behavior except for the administrator password.
- **D8A — Migration data** [settled]
- Migrate functional DNS configuration only.
- Constraint: Do not migrate query history or statistics.
- **D9A — Operations** [settled]
- Declares a newly generated bcrypt verifier in Nix.
- Constraint: Keep the plaintext password outside the repository and Nix store.
- Constraint: The verifier is readable from the Nix store.
- **D10A — Cutover and rollback** [settled]
- Uses a planned atomic cutover with rollback.
- Stop the Proxmox container before starting the guest.
- Validate the guest before restoring the Proxmox container during rollback.
- **D11A — Runtime-state backup** [settled]
- Do not back up rebuildable AdGuard Home runtime state.
- **D12A — Monitoring** [settled]
- Do not add DNS availability monitoring.
- **D13A — Upgrade ownership** [settled]
- The normal flake update and explicit NixOS rebuild workflow owns upgrades.
- Replace AdGuard Home. [not selected]
- **D2B — Replacement product** [not applicable]
- Choose Blocky, Pi-hole, Technitium, or a composed resolver.
## Frontier
None.
## Sources
- Pinned Nixpkgs module: `nixos/modules/services/networking/adguardhome.nix`.
- Pinned Nixpkgs modules: `blocky.nix`, `pihole-ftl.nix`, `pihole-web.nix`, `technitium-dns-server.nix`, `unbound.nix`, `dnscrypt-proxy.nix`, `knot-resolver.nix`, and `smartdns.nix`.
- AdGuard Home README, release `v0.107.79`.
- Technitium DNS Server README, current upstream.
-304
View File
@@ -1,304 +0,0 @@
# Deadnix Architecture
## Purpose
This note explains how `deadnix` finds unused Nix code.
It focuses on architecture, not whether each check belongs in our linter.
Use this note when deciding whether our linter needs scope analysis.
## What Deadnix Is
`deadnix` is a dead-code scanner for Nix.
It finds bindings that introduce names which no live code uses.
It is not a general style linter.
It does not have many independent rules.
It implements one analysis family: unused declarations.
Like `statix`, it parses source text with `rnix`.
It does not evaluate Nix.
It does not import files.
It reasons over local syntax and local scope only.
## Minimal Dead-Code Vocabulary
- A binding introduces a name.
- A scope defines where introduced names are visible.
- A use is an identifier occurrence that refers to a binding.
- Shadowing happens when an inner scope reuses an outer name.
- Dead code is a binding that no live code uses.
- A fixed point is the final result after repeated analysis no longer changes.
Dead-code analysis needs more state than a simple syntax lint.
It must know which names a scope introduces and where those names can be used.
## Component Map
`deadnix` has fewer layers than `statix`.
The command-line entry point, file walk, parsing, analysis, reporting, and editing live in one small tool.
The important concepts are separate modules:
- settings control analysis options;
- scopes describe where names are introduced;
- bindings describe individual declared names;
- usage search answers whether a name appears in a live body;
- dead-code results connect a binding to its scope;
- reports render findings;
- edits remove or rename unused declarations.
## Main Pipeline
```mermaid
flowchart TD
A[Parse CLI options] --> B[Collect input files]
B --> C[Read each file]
C --> D[Parse with rnix]
D --> E[Skip file on parse errors]
D --> F[Run dead-code analysis]
F --> G[Print reports unless quiet]
G --> H[Apply edits when --edit is set]
H --> I[Exit 1 when --fail and findings exist]
```
The CLI accepts files or directories.
Directory mode walks `.nix` files.
Hidden files require an explicit option.
Excludes filter paths before analysis.
The tool skips dead-code diagnostics when a file has parse errors.
It reports parse errors to the user and continues with other files.
## Analysis Settings
The analysis has four important switches.
`no_lambda_arg` disables checks for single lambda arguments.
This can avoid noise when an API requires an argument name.
`no_lambda_pattern_names` disables checks for names in attribute-set function patterns.
This matters for `callPackage`-style code, where argument names can be external API.
`no_underscore` ignores bindings that start with `_`.
This treats `_name` as an intentional unused placeholder.
`warn_used_underscore` reports underscore-prefixed bindings that code actually uses.
This enforces the convention that `_name` means unused.
These settings are architecture-relevant because dead-code policy depends on API context.
A repository linter needs a way to express that context.
## Scope Model
`deadnix` recognizes four scope types.
### Lambda pattern scope
A lambda pattern is a function argument written as an attribute set pattern.
It can introduce field names and an optional alias for the whole argument set.
Example shape:
```nix
args @ { pkgs, lib, ... }: body
```
This scope can introduce `args`, `pkgs`, and `lib`.
### Lambda argument scope
A single lambda argument introduces one name.
Example shape:
```nix
pkgs: body
```
This scope introduces `pkgs`.
### Let scope
A `let` expression introduces bindings and inherited names.
Those names are available in binding expressions and in the body.
Example shape:
```nix
let
inherit (pkgs) hello;
value = hello;
in
value
```
This scope introduces `hello` and `value`.
### Recursive attribute-set scope
A `rec` attribute set introduces names that sibling attributes can reference.
`deadnix` models this scope, but treats its bindings as non-removable.
That conservative choice avoids deleting public-looking attributes from recursive sets.
## Binding Model
A binding stores three facts.
It stores the identifier name.
It stores the syntax node that declared the name.
It stores whether the binding is mortal.
A mortal binding can become a dead-code finding.
A non-mortal binding participates in name lookup but will not be removed.
Single lambda arguments that already start with `_` are non-mortal.
Recursive attribute-set bindings are also non-mortal.
A binding also checks for the `deadnix: skip` pragma.
The pragma applies to a nearby following declaration.
The scanner searches backward from the declaration and stops after a blank-line boundary.
## Usage Search
Usage search asks whether a given name appears inside a syntax subtree.
The search is scope-aware.
When it enters a child scope that binds the same name, it stops following that branch.
That prevents an inner binding from counting as a use of an outer binding.
Attribute paths get special handling.
Ordinary attribute keys do not count as uses.
Dynamic or string attribute names can contain expressions, so the search looks inside those parts.
`inherit` also gets special handling.
A scope can inherit names from an outer scope.
The analysis checks whether the inherited expression uses the searched name.
## Fixed-Point Analysis
`deadnix` repeats the scan until the result set stops changing.
This matters because dead code can depend on other dead code.
A binding can appear used during the first pass because another binding references it.
If the referring binding is dead, the referenced binding is also dead.
The loop tracks dead declaration nodes.
During later scans, uses inside already-dead bodies do not keep other bindings alive.
This fixed-point loop is the central architectural difference from simple local syntax lints.
It makes dead-code results transitive.
## Reporting Model
A result stores the scope and binding for one finding.
The display text combines both parts.
Examples include unused lambda pattern, unused lambda argument, and unused let binding.
Human output uses `ariadne`.
The reporter groups ranges by line and labels the exact binding names.
It uses different colors for different scope kinds.
JSON output exists behind a feature flag.
It emits file, message, line, column, and end column.
`NO_COLOR` disables colored human output.
## Edit Model
`deadnix --edit` converts findings into text edits.
Each edit has a start offset, end offset, and replacement string.
The edit behavior depends on scope kind.
For unused lambda pattern names, it removes the name and nearby comma or whitespace.
For unused pattern aliases, it removes the alias syntax.
For unused lambda arguments, it renames the argument with an underscore prefix.
For unused `let` assignments, it deletes the assignment.
For unused inherited names, it deletes only the inherited name.
After those edits, it parses the edited source again.
Then it removes empty `let in` constructs and empty `inherit` statements.
This cleanup pass prevents the first edit batch from leaving invalid or useless scaffolding.
## Error Handling
If a path cannot be stated or read, the CLI reports the file error and continues.
If a file has parse errors, the CLI reports those errors and skips dead-code analysis for that file.
The `--fail` flag changes exit status when findings exist.
Without `--fail`, findings do not make the command fail.
This design separates report generation from CI policy.
## Architectural Strengths
The scope model is explicit.
Each scope type declares which bindings it introduces and where those bindings are visible.
The fixed-point loop catches transitive dead code.
A binding used only by dead code also becomes dead.
The usage search handles shadowing.
That prevents common false positives in nested functions and nested `let` expressions.
The edit model is tied to analysis results.
It knows whether a binding came from a lambda, pattern, `let`, or `inherit`.
The tool has few moving parts.
That makes the analysis easy to follow compared to a general multi-rule linter.
## Architectural Limits
`deadnix` does not evaluate Nix.
It cannot know which names external callers depend on.
This matters for module arguments, package function arguments, and public attribute sets.
It has global switches rather than project-specific rule contexts.
For example, all lambda pattern names can be checked or skipped.
The tool does not know that one directory contains `callPackage` functions.
The analysis is local to one file.
It cannot see that another file imports a function and relies on its argument names.
The fixer performs text edits with byte ranges.
It must handle punctuation and whitespace carefully.
Pattern edits are harder than simple assignment deletion.
The tool has one analysis family.
It is not a framework for many unrelated rules.
## Lessons for Our Linter
Dead-code checks need a scope pass.
A per-node rule interface is not enough when a diagnostic depends on name visibility.
Represent scopes explicitly.
Each scope type should provide introduced bindings and visible bodies.
Track shadowing before reporting unused names.
A text search for an identifier is not sufficient.
Use fixed-point analysis for transitive dead code.
One pass misses names used only by dead declarations.
Separate policy from mechanics.
The mechanics can find unused names.
Repository policy decides whether module arguments, package arguments, or underscore names count.
Treat autofix as scope-specific.
Removing a pattern name is not the same operation as deleting a `let` assignment.
Run cleanup after edits.
Dead-code fixes can create empty `let` expressions and empty `inherit` statements.
## Open Design Questions for Our Linter
- Should dead-code analysis be part of `nix-style-linter`, or a separate command?
- Should policy vary by path, file kind, or suppression comment?
- Should recursive attribute-set members ever become removable findings?
- Should underscore names mean ignored, or should used underscore names be errors?
- Should the linter report unused names without offering autofix first?
- Should cleanup rules run as ordinary rules or as a post-fix pass?
@@ -1,102 +0,0 @@
# Hyprland Lua Migration Plan
## Problem Statement
The Hyprland compositor config uses Home Manager's hyprlang output.
Hyprland deprecates hyprlang for the main compositor config.
The repository needs to generate a Lua config without changing desktop behavior.
## Solution
Keep the config owned by Nix and Home Manager.
Switch the Hyprland Home Manager config output to Lua.
Convert only the settings whose shape changes under Lua.
This is not a desktop redesign.
The change preserves the current monitors, binds, window rules, environment variables, and UWSM startup.
## User Stories
1. As the operator, I want Hyprland to load `hyprland.lua`, so that startup no longer warns about hyprlang deprecation.
2. As the operator, I want existing keyboard binds to keep working, so that the desktop behavior stays unchanged.
3. As the operator, I want host monitor layout to stay unchanged, so that the physical display setup does not move.
4. As the operator, I want session environment variables to stay in the compositor config, so that Wayland and cursor behavior stays unchanged.
5. As the operator, I want auxiliary module binds to keep working, so that launcher, lock, screenshot, clipboard, notifications, and recording flows stay usable.
## Implementation Decisions
1. Use Home Manager's Lua config generator.
Set the Hyprland config type to Lua and keep package ownership unchanged.
2. Keep ordinary compositor options declarative in Nix.
Move input, general, decoration, xwayland, animation, and layout settings into the Lua config structure.
3. Remove hyprlang-only variables from generated config.
Keep modifier and terminal values as Nix locals or helper inputs.
4. Add minimal local helpers for Lua calls.
Use helpers only for repeated bind, dispatcher, command, environment, and rule shapes.
5. Convert all bind strings to Lua bind call data.
Preserve key combinations, dispatchers, commands, repeat behavior, and locked-session behavior.
6. Convert contributed binds in their owning modules.
Keep each bind near the module that owns the tool it launches.
7. Convert monitor strings to Lua monitor records.
Preserve output names, modes, positions, scale values, and rotation.
8. Convert the screenshot window rule to the Lua rule shape.
Preserve the Satty class matcher and floating behavior.
9. Convert environment strings to Lua environment calls.
Preserve the Wayland flag and cursor variables.
10. Delete or update comments that describe hyprlang syntax.
Keep comments that explain behavior or non-obvious invariants.
## Testing Decisions
1. Run the repository Nix formatting and style checks for modified Nix files.
2. Evaluate or build the affected host configuration.
This proves Home Manager accepts the Lua settings structure.
3. Confirm the generated config file uses Lua.
The expected output is `hyprland.lua`, not `hyprland.conf`.
4. Verify Hyprland accepts the generated Lua config.
Use Hyprland config verification when the installed build supports it.
Otherwise reload the compositor and inspect errors.
5. Smoke test the changed desktop surface.
Test one bind from each source area after reload.
6. Check the explicit monitor layout on the host that declares it.
Confirm resolution, position, scale, and rotation stayed unchanged.
## Out of Scope
- Do not split the config into Lua modules.
- Do not hand-write a full Lua config.
- Do not add new Hyprland behavior.
- Do not change UWSM startup.
- Do not redesign binds, monitor layout, or visual settings.
- Do not change hyprlock, hypridle, waybar, mako, or rofi settings beyond their Hyprland binds.
## Further Notes
Home Manager documents `configType = "lua"` for Hyprland.
It maps settings to `hl.*` calls.
It supports `_args` for multi-argument calls.
It supports raw Lua expressions with `lib.generators.mkLuaInline`.
The riskiest parts are binds, monitor declarations, and window rules.
Those parts changed shape more than scalar config sections.
Assumption: the pinned Home Manager input contains the documented Lua Hyprland generator.
Validate this during the configuration build.
@@ -0,0 +1,130 @@
# NixOS AGENTS and style-skill scope design tree
This tree reviews `configs/nixos/AGENTS.md`.
It decides which instructions belong in Nix style rules.
## Known facts
- `configs/nixos/AGENTS.md` has 70 lines.
- Each frontier question quotes the complete instruction under review.
- This review decides instruction placement only.
- It supplies guidance for desktop, Firefox, Neovim, AI tooling, and NixOS gotchas.
- The `/review` prompt loads `nix-style` for Nix files.
- `nix-style` loads every rule under `src/skills/style/nix/rules/`.
- The current Nix rules cover Nix syntax and flake structure.
- `configs/nixos/AGENTS.md` includes a guest-module ownership rule.
- The RomM session missed that ownership rule during implementation.
- `registry.window-icon` exists in `configs/nixos/registry/window-icon.nix`.
- Desktop application modules declare window classes and rendered icons in that registry.
- Hyprland reads the registry to generate workspace icon mappings.
- The AGENTS instruction named the registry after its introduction on 2026-10-11.
- The `class` option describes its window-class match.
- The `icon` option describes a string icon value.
- The registry schema does not document the rendered-string requirement or the class-discovery command.
- Hyprland renders `config.registry.env` as its `env` configuration.
- The `env` registry replaced direct Hyprland environment declarations in commit `370cab8f8`.
- `configs/nixos/modules/desktop/apps/r2modman.nix` enables a graphical application without a `registry.window-icon` declaration.
- The current registry modules already validate value uniqueness and field combinations.
- They do not validate required producer declarations.
- The registry collector is specific to the NixOS dotfiles configuration.
- A non-discoverable environment fact records local behavior that configuration, source code, and normal tool help do not reveal.
- The current instruction groups are:
- Desktop: window icons, Hyprland environment variables, and cursor settings.
- Firefox: search-engine declarations and extension-storage compatibility.
- Neovim: Nixvim package-set selection.
- AI tooling: Herdr key names and Pi configuration locations.
- Gotchas: registry APIs, guest boundaries, SOPS ownership, guest mounts, deployment, DNS, hardware, module paths, and host commands.
## Decision tree
- Instruction review
- Settled: Review each complete instruction in source order.
- Registry conventions
- Settled: Create `src/skills/style/nix/rules/dotfiles.md`.
- Graphical application icon instruction
- Settled: Move the complete instruction to `src/skills/style/nix/rules/dotfiles.md`.
- Hyprland session environment instruction
- Settled: Remove it because `registry.env` superseded it.
- Firefox search-engine instruction
- Settled: Remove it because the Firefox module documents the configuration.
- Firefox extension-storage instruction
- Settled: Move it to a comment above `extensions.settings` in `modules/desktop/apps/firefox.nix`.
- Neovim package-set instruction
- Settled: Move it to a comment above `nixpkgs.useGlobalPackages` in `modules/shell/nvim/default.nix`.
- Herdr key-name instruction
- Settled: Remove it.
- Pi extension location instruction
- Settled: Remove it. It recorded a completed migration from NixOS-managed sources.
- Pi generated-settings instruction
- Settled: Remove it because the Pi module documents the managed boundary.
- Library-function qualification instruction
- Settled: Generalize it and move it to `src/skills/style/nix/rules/general.md`.
- Guest ownership instruction
- Settled: Move it to `src/skills/style/nix/rules/dotfiles.md`.
- SOPS guest-owner instruction
- Settled: Move it to `src/skills/style/nix/rules/dotfiles.md`.
- Nested guest-mount instruction
- Settled: Remove it because the example describes no active layout.
- `deploy-to` instruction
- Settled: Remove it. Agents cannot complete its remote sudo steps.
- Pikachu deploy-closure instruction
- Settled: Remove it because `deploy-to` encodes the required import path.
- Public-DNS instruction
- Settled: Remove it.
- Hardware-configuration instruction
- Settled: Remove it because the root auto-generated-file rule owns the policy.
- Chaotic-cache instruction
- Settled: Remove it because `modules.host.cachyos.enable` owns the cache configuration.
- Module-relative-path instruction
- Settled: Remove it because Nix evaluation reports invalid paths.
- Pikachu `uptime` instruction
- Settled: Remove it because the command exposes its supported options.
- Guest-ACME-evaluation instruction
- Settled: Remove it because current direct guest evaluation succeeds.
- systemd executable instruction
- Settled: Remove it because `general.md` already requires `lib.getExe'` for non-main executables.
## Frontier
The frontier is empty.
## Shared understanding
Remove these instructions from `configs/nixos/AGENTS.md`:
- Hyprland session environment
- Firefox search engines
- Herdr shifted punctuation
- Pi extension source location
- Pi managed settings
- Nested guest mounts
- `deploy-to` behavior
- Pikachu deploy closures
- Public DNS boundary
- Hardware configuration
- Chaotic cache selection
- Module-relative paths
- Pikachu boot time
- Guest ACME evaluation
- systemd executable selection
Move these instructions intact to `src/skills/style/nix/rules/dotfiles.md`:
- Graphical application icons
- Guest ownership
- SOPS guest ownership
Move the generalized library-function qualification convention to
`src/skills/style/nix/rules/general.md`.
Move these instructions to code comments:
- Firefox extension storage: above `extensions.settings` in
`configs/nixos/modules/desktop/apps/firefox.nix`
- Nixvim package set: above `nixpkgs.useGlobalPackages` in
`configs/nixos/modules/shell/nvim/default.nix`
The review does not decide how to restore the auto-generated status of
`configs/nixos/hosts/pikachu/hardware-configuration.nix`.
The operator confirmed this design and authorized the edits.
@@ -0,0 +1,98 @@
---
date-created: 2026-10-21 08:47
date-modified: 2026-10-21 09:26
---
# RetroArch on Zeus design tree
## Facts
- Zeus is an `x86_64-linux` desktop with AMD graphics, 32-bit graphics support, Bluetooth, Hyprland, and Home Manager.
- Nixpkgs provides `pkgs.retroarch.withCores` for an explicit set of Libretro cores.
- Nixpkgs provides `pkgs.retroarch-free` and `pkgs.retroarch-full` for broad core sets.
- The packaged RetroArch version is 1.22.2 and includes Cloud Sync on Linux.
- Linux Cloud Sync uses a WebDAV endpoint.
- RomM requires RetroArch 1.22 or newer for this integration.
- RomM documents configuration synchronization as part of its Cloud Sync setup.
- Cloud Sync supports saves, configuration, thumbnails, and system files as separate categories.
- RomM matches a save or state to a ROM by its file name without the extension.
- Local ROM files must use the same names as their RomM library records.
- RomM 5.4 provides a WebDAV endpoint for RetroArch Cloud Sync.
- The endpoint is `https://games.alexion.dev/api/sync/retroarch/`.
- RomM stores its ROMs and BIOS files on Pikachu.
## Constraints
- Install RetroArch on Zeus.
- Start with PlayStation and Sega Saturn cores.
- Evaluate RetroArch Cloud Sync.
- Keep package selection declarative.
- Keep credentials out of the Nix store and version control.
## Decision tree
- D1 — Initial core selection [settled]
- Use `beetle-psx-hw` for PlayStation.
- Use `beetle-saturn` for Sega Saturn.
- D4 — Core package viability [settled]
- Both core packages support `x86_64-linux`.
- Neither package is marked broken or unfree.
- D5 — Package composition [settled]
- Build a RetroArch wrapper with `beetle-psx-hw` and `beetle-saturn` only.
- D2 — Cloud Sync data scope [settled]
- Sync saves, states, and configuration.
- Do not sync thumbnails or system files.
- D6 — Sync endpoint [settled]
- Use RomM's RetroArch WebDAV endpoint.
- D7 — Sync identity [settled]
- Use the existing RomM account.
- D15 — Credential injection [settled]
- Store the RomM password in RetroArch's writable user configuration.
- D8 — Synchronization mode [settled]
- Synchronize automatically at startup and after play sessions.
- D16 — Launch order [settled]
- Do not add a game-launching frontend.
- Start RetroArch before loading local ROM content.
- D9 — Conflict and destructive-sync policy [settled]
- Use non-destructive synchronization.
- RetroArch backs up a local file when RomM reports its deletion.
- D3 — ROM and firmware access [settled]
- Keep ROMs and BIOS files locally on Zeus.
- D10 — Mount or replication method [settled]
- Do not configure a remote mount or replication method.
- D11 — RetroArch directory settings [settled]
- Use `~/.local/share/retroarch/`.
- Use `roms/`, `system/`, `saves/`, and `states/` subdirectories.
- Keep saves and states outside the content directory.
- Sort saves and states into per-core folders.
- D12 — User-configuration policy [settled]
- Nix declares the package, cores, and directory defaults.
- RetroArch manages and synchronizes its writable configuration.
- D13 — User-facing integration [settled]
- Do not add a user-facing integration beyond RetroArch's desktop entry.
- D14 — Validation [settled]
- Verify the NixOS evaluation and a manual Cloud Sync round trip.
## Frontier
No decisions remain open.
## Decision log
- D13: Do not add a user-facing integration beyond RetroArch's desktop entry.
- D16: Do not add a game-launching frontend. Start RetroArch before loading local ROM content.
- D14: Verify the NixOS evaluation and a manual Cloud Sync round trip.
- D12: Nix declares the package, cores, and directory defaults. RetroArch manages and synchronizes its writable configuration.
- D11: Use `~/.local/share/retroarch/` with `roms/`, `system/`, `saves/`, and `states/` subdirectories.
- D9: Use non-destructive synchronization.
- D8: Synchronize automatically at startup and after play sessions.
- D15: Store the RomM password in RetroArch's writable user configuration.
- D5: Build a RetroArch wrapper with `beetle-psx-hw` and `beetle-saturn` only.
- D3: Keep ROMs and BIOS files locally on Zeus.
- D10: Do not configure a remote mount or replication method.
- D7: Use the existing RomM account.
- D7 note: RomM accepts API client tokens as Bearer authentication. RetroArch Cloud Sync only supports WebDAV Basic authentication.
- D6: Use RomM's RetroArch WebDAV endpoint.
- D2: Sync saves, states, and configuration. Do not sync thumbnails or system files.
- D11: Keep saves and states outside the content directory. Sort them into per-core folders.
- D1: Use `beetle-psx-hw` for PlayStation and `beetle-saturn` for Sega Saturn.
- D4: Both selected core packages support Zeus and have no broken or unfree package status.
@@ -0,0 +1,107 @@
---
date-created: 2026-10-20 19:15
date-modified: 2026-10-20 19:20
---
# RomM 5.4 deployment changes
## Known facts
- The deployed Nixpkgs package is RomM 5.2.0.
- RomM 5.4.0 requires Python 3.14 or later.
- The pinned Nixpkgs contains Python 3.14.
- The pinned Python package set lacks some RomM 5.4.0 dependency versions.
- For example, it provides RQ 2.10 while RomM requires RQ 2.12 or later.
- In this design, upstream means the Nixpkgs repository.
- Nixpkgs upstream still packages RomM 5.2.0.
- Two open Nixpkgs pull requests update RomM to 5.4.0.
- Pull request 574089 adds a required compatibility patch for Nixpkgs Redis 8.0.1.
- Pull request 574089 has not run the NixOS module test.
- The existing `romm` derivation already uses Python 3.14 from the pin.
- The package can override the current derivation without copying it.
- The override evaluates successfully with the RomM 5.4.0 source and frontend hashes.
- RomM reads `config.yml` from `/var/lib/romm/config/config.yml`.
- Systemd tmpfiles `L+` replaces that path with a generated Nix-store symlink.
- NixOS modules use `L+` symlinks for declaratively managed files in persistent application directories.
- The existing Nixpkgs RomM NixOS test starts the application with PostgreSQL, Redis, nginx, and the filesystem watcher in a local VM.
- The test does not deploy to Pikachu.
- The automated update changes only the version, source hash, and frontend dependency hash.
- The manual update also removes a Redis maintenance-notification import and argument.
- RomM does not require the `rom-converto` executable while `ROM_CONVERTO_ENABLED` is false.
- As checked on 2026-10-20, both pull requests remain open.
- Neither pull request has a review or a discussion comment.
- Both pull requests request review from the RomM package maintainers.
- Both pull requests pass evaluation and lint checks.
- Their package-test checks have a neutral result.
- The Darwin package-test jobs remain queued.
- RomM 5.3.0 added a required `filesystem.structure` declaration.
- RomM will not start without that declaration.
- The existing mounts match Structure A.
- Structure A maps ROMs to `roms/{platform}/{game}`.
- Structure A maps firmware to `bios/{platform}`.
- RomM 5.4.0 enables `emulatorjs.auto_save_sync` by default.
- RomM 5.4.0 adds optional in-place library conversion through `rom-converto`.
- Library conversion requires `ROM_CONVERTO_ENABLED=true`.
- Conversion deletes original files after conversion.
- The task requires declarative `config.yml` management.
- The task requires disabled browser save synchronization.
- The task requires disabled library conversion.
- The task retains the IGDB, ScreenScraper, and SteamGridDB configuration.
- The task reuses the Nixpkgs `services.romm` module.
## Sources
- [RomM 5.3.0 release](https://github.com/rommapp/romm/releases/tag/5.3.0)
- [RomM 5.4.0 release](https://github.com/rommapp/romm/releases/tag/5.4.0)
- [RomM 5.4.0 configuration example](https://github.com/rommapp/romm/blob/5.4.0/examples/config.example.yml)
- [RomM 5.4.0 Python requirement](https://github.com/rommapp/romm/blob/5.4.0/pyproject.toml)
- [[0015-romm-5-4-package]]
## Decision tree
- RomM 5.4 deployment
- Package runtime
- Settled: Build the local package with Python 3.14.
- Package source
- Settled: Maintain a local package.
- Constraint: Do not rely on either unreviewed Nixpkgs pull request.
- Package exposure
- Settled: Expose the package as `pkgs.alexion.romm`.
- Library layout
- Settled: Manage `config.yml` declaratively with Nix.
- Configuration materialization
- Settled: Replace the configuration file with a Nix-store symlink on activation.
- Settled: Declare Structure A.
- Settled: Set `filesystem.structure.default` to `roms/{platform}/{game}`.
- Settled: Set `filesystem.structure.firmware` to `bios/{platform}`.
- File safety
- Settled: Keep library conversion disabled.
- Settled: Do not enable `ROM_CONVERTO_ENABLED`.
- Browser emulation
- Settled: Set `emulatorjs.auto_save_sync` to `false`.
- Existing integration
- Settled: Reuse `services.romm`.
- Settled: Keep IGDB, ScreenScraper, and SteamGridDB configuration unchanged.
- Validation
- Settled: Build the local package and the Pikachu configuration.
- Settled: Do not run a local NixOS VM test.
- Settled: The operator validates the deployment on Pikachu.
## Settled decisions
- Build a local RomM 5.4.0 package.
- Do not rely on either unreviewed Nixpkgs pull request.
- Expose the package as `pkgs.alexion.romm`.
- Reuse `services.romm`.
- Generate `config.yml` with Nix.
- Replace `config.yml` with a Nix-store symlink on activation.
- Declare Structure A with `roms/{platform}/{game}` and `bios/{platform}`.
- Keep `ROM_CONVERTO_ENABLED` disabled.
- Set `emulatorjs.auto_save_sync` to `false`.
- Keep IGDB, ScreenScraper, and SteamGridDB configuration unchanged.
- Build the local package and Pikachu configuration.
- Do not run a local NixOS VM test.
- Let the operator validate the deployment on Pikachu.
## Frontier
No in-scope decisions remain.
@@ -0,0 +1,106 @@
# RomM migration design tree
## Known facts
- RomM is listed under the Pikachu and Pichu Proxmox migration.
- Pikachu already runs VLAN 20 guests with persistent storage.
- Nixpkgs provides a tested `services.romm` module at version 5.2.0.
- `services.romm.dataDir` defaults to `/var/lib/romm`.
- RomM stores the game library below `/var/lib/romm/library`.
- RomM stores saves, states, user-uploaded screenshots, and profile avatars below `/var/lib/romm/assets/users/<user-id>/`.
- RomM derives `<user-id>` from its database ID, so it is not a stable configured username.
- RomM stores scraped covers and provider-sourced game screenshots below `/var/lib/romm/resources/roms/<platform-id>/<rom-id>/`.
- RomM 5.4.0 exists upstream but Nixpkgs does not package it.
- RomM 5.3.0 requires an explicit library-structure declaration in `config.yml`.
- The 5.4.0 package phase must add the Structure A declaration for `roms/{platform}/{game}` and `bios/{platform}`.
- RomM 5.4.0 can modify ROM files in place only when library conversion is explicitly enabled.
- RomM 5.3.0 identifies hashed ROMs by CRC, MD5, and SHA-1 after a scan.
- RomM 5.3.0 matches moved or renamed hashed ROMs to their existing database records.
- This migration is a fresh installation.
- The new library will receive selected ROMs from the old installation.
- Copyparty serves `/pikachu/media` as its writable `/media` volume.
## Decision tree
- RomM deployment
- Target location
- Settled: Deploy a dedicated guest on Pikachu.
- Package source
- Settled: Start with Nixpkgs's RomM 5.2.0 package.
- Settled: Package RomM 5.4.0 locally as follow-up work.
- Persistent storage
- Settled: Use `/var/lib/romm` in the guest.
- Settled: Mount `/pikachu/data/romm` at `/var/lib/romm`.
- Settled: Mount the ROM library separately at `/var/lib/romm/library`.
- Settled: Mount user assets separately for Copyparty browsing.
- Settled: Keep scraped resources in `/pikachu/data/romm`.
- Settled: Mount `/pikachu/media/games/emulation/roms` at `/var/lib/romm/library/roms`.
- Settled: Mount `/pikachu/media/games/emulation/bios` at `/var/lib/romm/library/bios`.
- Settled: Mount `/pikachu/media/games/emulation/users` at `/var/lib/romm/assets/users`.
- Settled: Mount `/pikachu/data/romm/postgresql` at `/var/lib/postgresql`.
- Settled: Mount `/pikachu/data/romm/redis` at `/var/lib/redis-romm`.
- Guest networking
- Settled: Follow the standard guest-provisioning protocol, including its VLAN 20 DHCP reservation.
- Public route
- Settled: Retain the old installation's public domain.
- Metadata and authentication secrets
- Settled: Configure IGDB, ScreenScraper, and SteamGridDB.
- Settled: Use RomM's default metadata and artwork priority.
- Settled: Manage the 5.4.0 `config.yml` declaratively with Nix.
- Settled: Use RomM's default region and English-language priority.
- Save synchronization
- Settled: Disable automatic browser save synchronization in 5.4.0.
- Authentication
- Settled: Use RomM's built-in accounts initially.
- Deferred: Configure RomM as an OpenID Connect client after an identity provider exists.
- ROM selection and import
- Settled: The operator manually selects and copies ROMs after deployment.
- Settled: Do not create automatic import tooling or a ROM manifest.
- Capacity and service limits
- Settled: Limit the guest to `4G` memory, `200%` CPU, and `512` tasks.
- Library scanning
- Settled: Enable the filesystem watcher for library changes.
- Cutover and retirement
- Out of scope: The operator manages the old installation and public-domain cutover outside this monorepo.
- Work phases
- Settled: Create a RomM guest module with Nixpkgs's package in [[0014-romm-guest]].
- Settled: Package RomM 5.4.0 locally and reuse `services.romm` in [[0015-romm-5-4-package]].
- Settled: Move selected ROMs after the service deployment is ready in [[0016-romm-manual-rom-migration]].
## Settled decisions
- **Migration model:** Start with a fresh RomM installation.
- **Data scope:** Copy selected ROMs from the old installation.
- **Old application state:** Do not migrate the database, users, sessions, or job queue.
- **Deployment target:** Deploy a dedicated guest on Pikachu.
- **Initial package:** Use Nixpkgs's RomM 5.2.0 package.
- **Package follow-up:** Package RomM 5.4.0 locally.
- **Work phases:** Deploy the guest, update the package, then import selected ROMs.
- **Guest data directory:** Use RomM's default `/var/lib/romm`.
- **Host application data:** Mount `/pikachu/data/romm` at `/var/lib/romm`.
- **ROM library:** Mount it separately at `/var/lib/romm/library`.
- **Storage classification:** Preserve the distinction between application data and browsable media.
- **User assets:** Mount `/pikachu/media/games/emulation/users` at `/var/lib/romm/assets/users` to expose saves, states, user-uploaded screenshots, and profile avatars through Copyparty.
- **ROM paths:** Mount `/pikachu/media/games/emulation/roms` and `/pikachu/media/games/emulation/bios` at the corresponding children of `/var/lib/romm/library`.
- **Guest networking:** Follow the standard guest-provisioning protocol.
- **Public route:** Retain the old installation's public domain.
- **Metadata providers:** Configure IGDB, ScreenScraper, and SteamGridDB in both package phases.
- **Metadata priority:** Use RomM's default metadata and artwork priority.
- **RomM configuration:** Manage the required 5.4.0 `config.yml` declaratively with Nix.
- **Scan region and language priority:** Use RomM's defaults.
- **Initial authentication:** Use RomM's built-in accounts.
- **OIDC follow-up:** Track it in [[0013-oidc-provider]].
- **ROM migration:** The operator manually selects and copies ROMs after deployment.
- **Guest limits:** Cap the guest at `4G` memory, `200%` CPU, and `512` tasks.
- **Library watcher:** Enable the filesystem watcher.
- **PostgreSQL:** Mount `/pikachu/data/romm/postgresql` at `/var/lib/postgresql`.
- **Redis:** Mount `/pikachu/data/romm/redis` at `/var/lib/redis-romm`.
- **Browser save synchronization:** Disable it in 5.4.0 until browser emulation is needed.
## Frontier
No in-scope decisions remain.
## Next question
None. Present the settled design for confirmation before implementation.
@@ -0,0 +1,109 @@
---
date-created: 2026-10-20 17:45
date-modified: 2026-10-20 17:52
---
# SteamVR to Meta Quest 3 design tree
## Goal
Stream PCVR from Zeus to a Meta Quest 3.
The design must produce a repeatable and diagnosable SteamVR session.
## Observed facts
- Zeus runs NixOS with a CachyOS kernel.
- Zeus uses an AMD Radeon RX 9070-series GPU with the `amdgpu` driver.
- Zeus runs Hyprland on Wayland.
- Zeus has Steam and Gamescope configured.
- SteamVR 2.17.10 is installed.
- SteamVR includes Valve's Linux `vrlink` driver.
- A previous `vrlink` session detected the Quest 3 and its Touch controllers.
- That session selected 90 Hz from the Quest's 72, 80, 90, and 120 Hz modes.
- SteamVR setup lacks `cap_sys_nice` on `vrcompositor-launcher`.
- NixOS can declare host packages, permissions, services, and diagnostics.
- Steam owns the Quest pairing and SteamVR user settings.
- Zeus connects by Ethernet at `10.23.50.221`.
- The local Wi-Fi scan finds the `Tracion` 5 GHz network at 5220 MHz.
- The scan reports a 1170 Mbit/s link rate.
- The operator has no external tracked devices.
## Decision tree
- **D1: Host platform commitment** — Settled: Linux-native on the current NixOS installation.
- Linux-native on the current NixOS installation.
- **D2: Transport** — Blocked by D1
- Wireless LAN. — Settled: primary transport.
- **D3: Streaming stack** — Settled: SteamVR with its built-in VRLink driver.
- SteamVR with its built-in VRLink driver.
- **D3a: SteamVR acceptance criteria** — Settled: reliable session test.
- Run a SteamVR game for 30 minutes at 90 Hz.
- Verify visuals, audio, and Touch controllers.
- Verify one reconnect.
- ALVR only after SteamVR fails the agreed acceptance criteria.
- **D4: Wi-Fi topology** — Settled: keep the current access point.
- Keep the current access point.
- Add a dedicated access point.
- Use a direct Wi-Fi link.
- **D5: Session performance target** — Settled: selectable refresh-rate profiles.
- Selectable refresh-rate profiles.
- **D5a: Default refresh rate** — Settled: 90 Hz.
- **D5b: Included refresh rates** — Settled: 72, 80, 90, and 120 Hz.
- **D6: Network isolation** — Settled: existing trusted LAN.
- Existing trusted LAN.
- Dedicated VR VLAN or SSID.
- **D7: Controller and tracking scope** — Settled: Quest Touch controllers only.
- Quest Touch controllers only.
- Also support external tracked devices.
- **D8: Launch workflow** — Settled: automatic service and headset connection.
- Start SteamVR when Steam Link connects from the Quest.
- **D9: Diagnostics and recovery** — Settled: capture health checks and logs.
- Capture SteamVR logs and health checks.
- Recover failed sessions manually.
- USB tether.
- **D10: USB streaming stack** — Blocked by D2
- ALVR over USB.
- Meta Quest Link through a Windows installation.
- **D11: USB role** — Blocked by D2
- Primary transport.
- Fallback transport.
- Both wireless LAN and USB tether.
- **D12: Primary transport** — Blocked by D2
- **D13: Fallback behavior** — Blocked by D12
- **D14: System integration** — Settled: hybrid configuration.
- NixOS manages system integration.
- Steam manages Quest pairing and user settings.
- Dual-boot or replace NixOS with Windows.
- **D15: Windows streaming stack** — Blocked by D1
- Steam Link.
- Virtual Desktop.
- Meta Quest Link or Air Link.
- ALVR.
- **D16: Windows installation scope** — Blocked by D1
- Dedicated VR installation.
- General-use Windows installation.
- **D2: Transport** — Blocked by D1
- Keep NixOS and add a separate Windows VR host.
- **D17: Host placement** — Blocked by D1
- **D15: Windows streaming stack** — Blocked by D17
- **D2: Transport** — Blocked by D17
## Frontier
None.
## Settled decisions
- **D1: Host platform commitment** — Linux-native on the current NixOS installation.
- **D2: Transport** — Wireless LAN as the primary transport.
- **D4: Wi-Fi topology** — Keep the current access point.
- **D5: Session performance target** — Selectable profiles at 72, 80, 90, and 120 Hz.
- **D5a: Default refresh rate** — 90 Hz.
- **D5b: Included refresh rates** — 72, 80, 90, and 120 Hz.
- **D6: Network isolation** — Existing trusted LAN.
- **D7: Controller and tracking scope** — Quest Touch controllers only.
- **D3: Streaming stack** — SteamVR with its built-in VRLink driver.
- **D3a: SteamVR acceptance criteria** — 30-minute session at 90 Hz, with visuals, audio, Touch controllers, and one reconnect.
- **D8: Launch workflow** — Start SteamVR when Steam Link connects from the Quest.
- **D9: Diagnostics and recovery** — Capture health checks and logs. Recover failed sessions manually.
- **D14: System integration** — NixOS manages system integration. Steam manages Quest pairing and user settings.
+36
View File
@@ -0,0 +1,36 @@
# TL;DR command design tree
This tree reviews the implementation decisions in `tldr-design.md`.
## Settled decisions
- **Command form and scope:** Add the project prompt template `.pi/prompts/tldr.md`.
- **Explicit source interface:** Interpret command arguments as a free-form source request.
- **Default source:** Summarize the preceding agent response when no source request exists.
- **Summary shape:** Produce a compact summary without a fixed format.
- **Unavailable or unclear sources:** Add no special handling policy.
## Decision tree
- Command behavior
- Source selection
- Settled: Use the preceding agent response without arguments.
- Settled: Interpret arguments as a free-form source request.
- Output
- Settled: Produce a compact summary without a fixed format.
- Summary language
- Settled: Do not prescribe a language policy.
- Error behavior
- Settled: Add no special handling policy for unavailable or unclear sources.
## Frontier
The frontier is empty.
## Shared understanding pending confirmation
The project gets a `/tldr` prompt command in `.pi/prompts/tldr.md`.
Without arguments, it summarizes the preceding agent response.
With arguments, it interprets them as a free-form source request.
It produces a compact summary with no fixed format or language policy.
The prompt adds no special policy for unavailable or unclear sources.
+39
View File
@@ -0,0 +1,39 @@
# TL;DR command design
## Goal
Add a Pi command that summarizes the preceding agent response by default.
An explicit command argument identifies the source to summarize.
## Decision tree
- Command form and scope
- Settled: Create a project prompt template at `.pi/prompts/tldr.md`.
- Command interface
- Settled: Pass arguments through as a free-form source request.
- Default source selection
- Settled: Summarize the preceding agent response when no source request exists.
- Summary format and length
- Settled: Use a compact, format-free summary.
- Ambiguous-source behavior
- Settled: Add no special handling policy.
## Settled decisions
- **Q1 — Command form and scope:** Create a project prompt template.
- **Q2 — Explicit source interface:** Accept a free-form source request.
- **Default source selection:** Summarize the preceding agent response when the command has no arguments.
- **Q3 — Summary shape:** Use a compact, format-free summary.
- **Q4 — Unavailable source:** Add no special handling policy.
## Frontier
The frontier is empty.
## Shared understanding pending confirmation
The project gets a `/tldr` prompt command in `.pi/prompts/tldr.md`.
Without arguments, it summarizes the preceding agent response.
With arguments, it interprets them as a free-form source request.
It produces a compact summary with no fixed format.
The prompt adds no special policy for unavailable or unclear sources.
+14
View File
@@ -0,0 +1,14 @@
---
aliases:
- Credits
date-created: 2026-10-17 18:08
date-modified: 2026-10-17 23:33
---
# Credits
| Path | Original | Notes | |
|-------------------------------------|-----------------------------------------------------------------------------------------|-------|---|
| `//src/skills/agent-writing-skills` | <https://github.com/mattpocock/skills/tree/main/skills/productivity/writing-for-agents> | | |
| `//src/skills/retrospect` | <https://github.com/mattpocock/skills/tree/main/skills/engineering/retro> | | |
| | | | |
Loaded 100 of 2985 files, more files were not shown because too many files have changed in this diff. Show more