Compare commits
76
Commits
250b0b71f9
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d342370b89 | ||
|
|
c370d635e5 | ||
|
|
8756bc087f | ||
|
|
bb22a90053 | ||
|
|
5cf7109eaf | ||
|
|
4baafb7094 | ||
|
|
0166547091 | ||
|
|
1a2a4bd2bd | ||
|
|
94eb132962 | ||
|
|
8e01e1621b | ||
|
|
b4e74fc5b2 | ||
|
|
bbac95cac0 | ||
|
|
e5bacc53be | ||
|
|
5f52a78efa | ||
|
|
dc210d4985 | ||
|
|
2237c3eea3 | ||
|
|
771a0df831 | ||
|
|
cfa01fb550 | ||
|
|
7186d6a3a7 | ||
|
|
c836396cbe | ||
|
|
3493519085 | ||
|
|
f160fd15a2 | ||
|
|
f1a93199c7 | ||
|
|
591144df33 | ||
|
|
d7760ef84d | ||
|
|
042238476a | ||
|
|
e41b8e3eb4 | ||
|
|
63017f8e33 | ||
|
|
52f31fd44d | ||
|
|
898a6df333 | ||
|
|
5a5543633c | ||
|
|
9c501a79ad | ||
|
|
30e5b1e677 | ||
|
|
45a840002f | ||
|
|
a9db1f8b7c | ||
|
|
dcc4efcc75 | ||
|
|
a23a317335 | ||
|
|
6e545c0a15 | ||
|
|
6081e3e325 | ||
|
|
719370c8f7 | ||
|
|
2b4e66a75c | ||
|
|
c44769ff70 | ||
|
|
1397576538 | ||
|
|
5fbe1850e0 | ||
|
|
57bb21af1a | ||
|
|
ffc40e547b | ||
|
|
55f61f71d8 | ||
|
|
08563c6769 | ||
|
|
8462b3a5a8 | ||
|
|
d0872e7d8c | ||
|
|
9be9ad7675 | ||
|
|
5ee328cdf8 | ||
|
|
6532a822cd | ||
|
|
20a3990979 | ||
|
|
b7ab518f58 | ||
|
|
3f1e34ef95 | ||
|
|
d0abfc1625 | ||
|
|
031090e4ea | ||
|
|
2edad6c5df | ||
|
|
1d5acc09c6 | ||
|
|
ee29e53f7c | ||
|
|
3c9d0ec886 | ||
|
|
f0c5544b10 | ||
|
|
4dd0a5a4f5 | ||
|
|
a4a795f7ee | ||
|
|
ecdf877308 | ||
|
|
d1face10ec | ||
|
|
337d9a2014 | ||
|
|
f059068873 | ||
|
|
7662c04cda | ||
|
|
33128fc3c7 | ||
|
|
68415ad47e | ||
|
|
6b7201e6fa | ||
|
|
4360f4863b | ||
|
|
370cab8f83 | ||
|
|
e74a08b853 |
No files matched your search
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
Symlink
+1
@@ -0,0 +1 @@
|
|||||||
|
../../src/skills/agent-writing-guide
|
||||||
Symlink
+1
@@ -0,0 +1 @@
|
|||||||
|
../../src/skills/conventional-commits
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../src/skills/craft-skill
|
|
||||||
Symlink
+1
@@ -0,0 +1 @@
|
|||||||
|
../../src/skills/retrospect
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../src/skills/to-document
|
|
||||||
@@ -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
@@ -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,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" }
|
||||||
@@ -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.
|
|
||||||
@@ -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
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -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";
|
||||||
|
|||||||
@@ -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";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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"}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -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";
|
||||||
|
|||||||
@@ -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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -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"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -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}";
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -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";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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 = {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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 = {
|
||||||
|
|||||||
@@ -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 ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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}";
|
||||||
|
|||||||
@@ -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";
|
||||||
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -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";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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; [
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|||||||
@@ -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 ];
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{ lib, ... }:
|
||||||
|
{
|
||||||
|
type = lib.types.str;
|
||||||
|
}
|
||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -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 = "";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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
@@ -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"
|
||||||
]
|
]
|
||||||
Vendored
+15
-1
@@ -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
@@ -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
@@ -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 */
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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)}
|
||||||
Vendored
+33
-47
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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
Reference in new issue
Block a user