Improve developer documentation

This commit is contained in:
Jordan Wages 2026-07-07 01:31:52 -05:00
commit ab7b83abbb
48 changed files with 679 additions and 576 deletions

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

View file

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../">
@ -63,23 +63,9 @@
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>

File diff suppressed because one or more lines are too long

View file

@ -73,6 +73,94 @@
<article data-uid="">
<h1 id="getting-started">Getting Started</h1>
<p>This guide shows the common setup and first-use patterns for consuming CapyKit from a .NET 8 project.</p>
<h2 id="install">Install</h2>
<p>Add CapyKit to your project from NuGet:</p>
<pre><code class="lang-bash">dotnet add package CapyKit
</code></pre>
<p>If you are working from a local checkout instead, reference the project directly:</p>
<pre><code class="lang-bash">dotnet add reference ../CapyKit/CapyKit.csproj
</code></pre>
<h2 id="add-namespaces">Add Namespaces</h2>
<p>Most APIs live in one of three namespaces:</p>
<pre><code class="lang-csharp">using CapyKit;
using CapyKit.Extensions;
using CapyKit.Helpers;
</code></pre>
<p>Use <code>CapyKit</code> for core types such as <code>Password</code>, <code>Pool&lt;T&gt;</code>, and <code>CapyEventReporter</code>. Use <code>CapyKit.Extensions</code> for extension methods. Use <code>CapyKit.Helpers</code> for serialization, compression, security, keys, language, and calculation helpers.</p>
<h2 id="work-with-strings">Work With Strings</h2>
<pre><code class="lang-csharp">using CapyKit.Extensions;
string? suppliedName = &quot;&quot;;
string name = suppliedName.IfNullOrWhiteSpace(&quot;Guest&quot;);
</code></pre>
<p><code>IfNullOrEmpty</code> and <code>IfNullOrWhiteSpace</code> return the original value when it is usable and return your replacement value when it is not.</p>
<h2 id="page-and-filter-collections">Page And Filter Collections</h2>
<pre><code class="lang-csharp">using CapyKit.Extensions;
var activeUsers = users.Filter(user =&gt; user.Disabled);
var secondPage = activeUsers.Page(pageNumber: 2, pageSize: 25);
int pageCount = activeUsers.PageCount(pageSize: 25);
</code></pre>
<p><code>Filter</code> removes items that match the predicate. <code>Page</code> uses natural page numbering, so the first page is <code>1</code>.</p>
<h2 id="serialize-and-compress-data">Serialize And Compress Data</h2>
<pre><code class="lang-csharp">using CapyKit.Helpers;
var json = SerializationHelper.SerializeToString(order);
var copy = SerializationHelper.Deserialize&lt;Order&gt;(json);
var compressed = CompressionHelper.CompressToString(order);
var restored = CompressionHelper.Decompress&lt;Order&gt;(compressed);
</code></pre>
<p>Serialization uses <code>System.Text.Json</code>. Compression stores the serialized JSON payload using gzip; <code>CompressToString</code> returns a Base64 representation for easier storage or transport.</p>
<h2 id="hash-and-verify-passwords">Hash And Verify Passwords</h2>
<pre><code class="lang-csharp">using CapyKit;
using CapyKit.Helpers;
Password storedPassword = SecurityHelper.Pbkdf2(&quot;correct horse battery staple&quot;);
bool passwordMatches = SecurityHelper.CompareHashedPassword(
storedPassword,
&quot;correct horse battery staple&quot;,
storedPassword.Salt,
Password.Pbkdf2Algorithm);
</code></pre>
<p><code>SecurityHelper.Pbkdf2</code> creates a <code>Password</code> with a random salt. Store the hash, salt, and algorithm information required by your application, then compare future password attempts using the same salt and algorithm.</p>
<h2 id="generate-random-values">Generate Random Values</h2>
<pre><code class="lang-csharp">using CapyKit.Helpers;
string token = SecurityHelper.GetRandomString(32);
string password = SecurityHelper.GetRandomPassword(
20,
ValidCharacterCollection.Lowercase,
ValidCharacterCollection.Uppercase,
ValidCharacterCollection.Numbers,
ValidCharacterCollection.Special);
</code></pre>
<p>Random string and password generation use .NET cryptographic random number generation.</p>
<h2 id="create-and-validate-keys">Create And Validate Keys</h2>
<pre><code class="lang-csharp">using System.Text;
using CapyKit.Helpers;
var keyHelper = new KeyHelper();
keyHelper.SetMasterKeyAccessor(() =&gt; Encoding.UTF8.GetBytes(&quot;replace-with-your-master-key&quot;));
keyHelper.SetSaltSizeAccessor(() =&gt; 8);
keyHelper.SetNumPartsAccessor(() =&gt; 4);
string key = keyHelper.GenerateKey();
bool valid = keyHelper.ValidateKey(key);
</code></pre>
<p><code>KeyHelper</code> uses an application-provided master key to sign generated key material. Keep the master key secret and stable for keys that must remain valid over time.</p>
<h2 id="subscribe-to-capykit-events">Subscribe To CapyKit Events</h2>
<pre><code class="lang-csharp">using CapyKit;
CapyEventReporter.Subscribe(
e =&gt; Console.WriteLine($&quot;[{e.Level}] {e.MethodName}: {e.Message}&quot;),
EventLevel.Warning);
</code></pre>
<p>CapyKit does not require a logging framework. Subscribe to events and forward them to whatever logging or telemetry system your application already uses.</p>
<h2 id="browse-the-api">Browse The API</h2>
<p>For the full list of namespaces, types, overloads, and member signatures, open the generated <a href="api/toc.html">API Reference</a>.</p>
</article>

View file

@ -2,9 +2,9 @@
<html>
<head>
<meta charset="utf-8">
<title>This is the HOMEPAGE. | CapyKit Documentation </title>
<title>CapyKit Documentation | CapyKit Documentation </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="This is the HOMEPAGE. | CapyKit Documentation ">
<meta name="title" content="CapyKit Documentation | CapyKit Documentation ">
<link rel="icon" href="favicon.ico">
@ -71,13 +71,58 @@
</div>
<article data-uid="">
<h1 id="this-is-the-homepage">This is the <strong>HOMEPAGE</strong>.</h1>
<h1 id="capykit-documentation">CapyKit Documentation</h1>
<p>Refer to <a href="http://daringfireball.net/projects/markdown/">Markdown</a> for how to write markdown files.</p>
<h2 id="quick-start-notes">Quick Start Notes:</h2>
<ol>
<li>Add images to the <em>images</em> folder if the file is referencing an image.</li>
</ol>
<p>CapyKit is a small .NET utility library for the code you end up writing repeatedly: collection helpers, string and enum extensions, JSON serialization, gzip compression, password hashing, random token generation, simple key validation, distance calculations, and lightweight event reporting.</p>
<p>The library targets .NET 8 and keeps its public surface intentionally direct. Most features are static helpers or extension methods, so consuming projects can adopt one piece at a time without taking on a framework or application model.</p>
<h2 id="start-here">Start Here</h2>
<ul>
<li><a href="introduction.html">Introduction</a> explains what CapyKit includes and how the namespaces are organized.</li>
<li><a href="getting-started.html">Getting Started</a> shows installation, imports, and common usage examples.</li>
<li><a href="api/toc.html">API Reference</a> contains the generated DocFX reference for every public type and member.</li>
</ul>
<h2 id="common-tasks">Common Tasks</h2>
<h3 id="work-with-strings-and-collections">Work with strings and collections</h3>
<p>Use <code>CapyKit.Extensions</code> for small quality-of-life helpers such as null fallback values, pagination, inverted filtering, left outer joins, enum display names, and property copying.</p>
<pre><code class="lang-csharp">using CapyKit.Extensions;
var displayName = user.Name.IfNullOrWhiteSpace(&quot;Guest&quot;);
var page = users.Page(pageNumber: 2, pageSize: 25);
</code></pre>
<h3 id="serialize-compress-and-restore-values">Serialize, compress, and restore values</h3>
<p>Use <code>CapyKit.Helpers.SerializationHelper</code> and <code>CapyKit.Helpers.CompressionHelper</code> when you need straightforward JSON serialization or gzip compression around serializable values.</p>
<pre><code class="lang-csharp">using CapyKit.Helpers;
var payload = SerializationHelper.SerializeToString(order);
var compressed = CompressionHelper.CompressToString(order);
var restored = CompressionHelper.Decompress&lt;Order&gt;(compressed);
</code></pre>
<h3 id="hash-passwords-and-generate-tokens">Hash passwords and generate tokens</h3>
<p>Use <code>SecurityHelper</code> for PBKDF2 password hashes, salts, and random values backed by .NET cryptographic random number generation.</p>
<pre><code class="lang-csharp">using CapyKit;
using CapyKit.Helpers;
Password password = SecurityHelper.Pbkdf2(&quot;correct horse battery staple&quot;);
bool matches = SecurityHelper.CompareHashedPassword(
password,
&quot;correct horse battery staple&quot;,
password.Salt,
Password.Pbkdf2Algorithm);
</code></pre>
<h3 id="listen-to-capykit-events">Listen to CapyKit events</h3>
<p>CapyKit reports warnings and errors through <code>CapyEventReporter</code> instead of choosing a logging framework for you. Subscribe at the level your application cares about and route events into your own logging pipeline.</p>
<pre><code class="lang-csharp">using CapyKit;
CapyEventReporter.Subscribe(
e =&gt; logger.LogWarning(&quot;{Method}: {Message}&quot;, e.MethodName, e.Message),
EventLevel.Warning);
</code></pre>
<h2 id="build-the-docs-locally">Build The Docs Locally</h2>
<p>The documentation is generated with DocFX from the Markdown files in this folder and the XML comments in the <code>CapyKit</code> project.</p>
<pre><code class="lang-bash">dotnet tool install -g docfx
docfx Docs/docfx.json --serve
</code></pre>
<p>DocFX writes the generated site to <code>Docs/_site</code>.</p>
</article>

View file

@ -182,16 +182,16 @@
"getting-started.html": {
"href": "getting-started.html",
"title": "Getting Started | CapyKit Documentation",
"summary": "Getting Started"
"summary": "Getting Started This guide shows the common setup and first-use patterns for consuming CapyKit from a .NET 8 project. Install Add CapyKit to your project from NuGet: dotnet add package CapyKit If you are working from a local checkout instead, reference the project directly: dotnet add reference ../CapyKit/CapyKit.csproj Add Namespaces Most APIs live in one of three namespaces: using CapyKit; using CapyKit.Extensions; using CapyKit.Helpers; Use CapyKit for core types such as Password, Pool<T>, and CapyEventReporter. Use CapyKit.Extensions for extension methods. Use CapyKit.Helpers for serialization, compression, security, keys, language, and calculation helpers. Work With Strings using CapyKit.Extensions; string? suppliedName = \"\"; string name = suppliedName.IfNullOrWhiteSpace(\"Guest\"); IfNullOrEmpty and IfNullOrWhiteSpace return the original value when it is usable and return your replacement value when it is not. Page And Filter Collections using CapyKit.Extensions; var activeUsers = users.Filter(user => user.Disabled); var secondPage = activeUsers.Page(pageNumber: 2, pageSize: 25); int pageCount = activeUsers.PageCount(pageSize: 25); Filter removes items that match the predicate. Page uses natural page numbering, so the first page is 1. Serialize And Compress Data using CapyKit.Helpers; var json = SerializationHelper.SerializeToString(order); var copy = SerializationHelper.Deserialize<Order>(json); var compressed = CompressionHelper.CompressToString(order); var restored = CompressionHelper.Decompress<Order>(compressed); Serialization uses System.Text.Json. Compression stores the serialized JSON payload using gzip; CompressToString returns a Base64 representation for easier storage or transport. Hash And Verify Passwords using CapyKit; using CapyKit.Helpers; Password storedPassword = SecurityHelper.Pbkdf2(\"correct horse battery staple\"); bool passwordMatches = SecurityHelper.CompareHashedPassword( storedPassword, \"correct horse battery staple\", storedPassword.Salt, Password.Pbkdf2Algorithm); SecurityHelper.Pbkdf2 creates a Password with a random salt. Store the hash, salt, and algorithm information required by your application, then compare future password attempts using the same salt and algorithm. Generate Random Values using CapyKit.Helpers; string token = SecurityHelper.GetRandomString(32); string password = SecurityHelper.GetRandomPassword( 20, ValidCharacterCollection.Lowercase, ValidCharacterCollection.Uppercase, ValidCharacterCollection.Numbers, ValidCharacterCollection.Special); Random string and password generation use .NET cryptographic random number generation. Create And Validate Keys using System.Text; using CapyKit.Helpers; var keyHelper = new KeyHelper(); keyHelper.SetMasterKeyAccessor(() => Encoding.UTF8.GetBytes(\"replace-with-your-master-key\")); keyHelper.SetSaltSizeAccessor(() => 8); keyHelper.SetNumPartsAccessor(() => 4); string key = keyHelper.GenerateKey(); bool valid = keyHelper.ValidateKey(key); KeyHelper uses an application-provided master key to sign generated key material. Keep the master key secret and stable for keys that must remain valid over time. Subscribe To CapyKit Events using CapyKit; CapyEventReporter.Subscribe( e => Console.WriteLine($\"[{e.Level}] {e.MethodName}: {e.Message}\"), EventLevel.Warning); CapyKit does not require a logging framework. Subscribe to events and forward them to whatever logging or telemetry system your application already uses. Browse The API For the full list of namespaces, types, overloads, and member signatures, open the generated API Reference."
},
"index.html": {
"href": "index.html",
"title": "This is the HOMEPAGE. | CapyKit Documentation",
"summary": "This is the HOMEPAGE. Refer to Markdown for how to write markdown files. Quick Start Notes: Add images to the images folder if the file is referencing an image."
"title": "CapyKit Documentation | CapyKit Documentation",
"summary": "CapyKit Documentation CapyKit is a small .NET utility library for the code you end up writing repeatedly: collection helpers, string and enum extensions, JSON serialization, gzip compression, password hashing, random token generation, simple key validation, distance calculations, and lightweight event reporting. The library targets .NET 8 and keeps its public surface intentionally direct. Most features are static helpers or extension methods, so consuming projects can adopt one piece at a time without taking on a framework or application model. Start Here Introduction explains what CapyKit includes and how the namespaces are organized. Getting Started shows installation, imports, and common usage examples. API Reference contains the generated DocFX reference for every public type and member. Common Tasks Work with strings and collections Use CapyKit.Extensions for small quality-of-life helpers such as null fallback values, pagination, inverted filtering, left outer joins, enum display names, and property copying. using CapyKit.Extensions; var displayName = user.Name.IfNullOrWhiteSpace(\"Guest\"); var page = users.Page(pageNumber: 2, pageSize: 25); Serialize, compress, and restore values Use CapyKit.Helpers.SerializationHelper and CapyKit.Helpers.CompressionHelper when you need straightforward JSON serialization or gzip compression around serializable values. using CapyKit.Helpers; var payload = SerializationHelper.SerializeToString(order); var compressed = CompressionHelper.CompressToString(order); var restored = CompressionHelper.Decompress<Order>(compressed); Hash passwords and generate tokens Use SecurityHelper for PBKDF2 password hashes, salts, and random values backed by .NET cryptographic random number generation. using CapyKit; using CapyKit.Helpers; Password password = SecurityHelper.Pbkdf2(\"correct horse battery staple\"); bool matches = SecurityHelper.CompareHashedPassword( password, \"correct horse battery staple\", password.Salt, Password.Pbkdf2Algorithm); Listen to CapyKit events CapyKit reports warnings and errors through CapyEventReporter instead of choosing a logging framework for you. Subscribe at the level your application cares about and route events into your own logging pipeline. using CapyKit; CapyEventReporter.Subscribe( e => logger.LogWarning(\"{Method}: {Message}\", e.MethodName, e.Message), EventLevel.Warning); Build The Docs Locally The documentation is generated with DocFX from the Markdown files in this folder and the XML comments in the CapyKit project. dotnet tool install -g docfx docfx Docs/docfx.json --serve DocFX writes the generated site to Docs/_site."
},
"introduction.html": {
"href": "introduction.html",
"title": "Introduction | CapyKit Documentation",
"summary": "Introduction"
"summary": "Introduction CapyKit is a practical toolkit for .NET applications. It collects common helpers and extension methods into one package so application code can stay focused on business behavior instead of re-implementing the same plumbing in every project. The project began as shared infrastructure for HappyCapy and is now available as a standalone library. It currently targets .NET 8. What CapyKit Provides Extension Methods The CapyKit.Extensions namespace contains helpers for common language and LINQ tasks: StringExtensions provides fallback helpers such as IfNullOrEmpty and IfNullOrWhiteSpace. LINQExtensions adds pagination, page counts, inverted filtering, and left outer join helpers for enumerable and queryable collections. EnumerationExtensions makes enum names, numeric values, descriptions, and human-readable names easier to retrieve. ObjectExtensions copies matching writable properties from one object to another. Helper Classes The CapyKit.Helpers namespace contains focused utility classes: SerializationHelper serializes and deserializes values with System.Text.Json. CompressionHelper compresses serialized values with gzip and can represent compressed data as Base64. SecurityHelper creates PBKDF2 password hashes, salts, random strings, and random passwords. KeyHelper creates and validates formatted HMAC-backed keys using a caller-provided master key. CalculationHelper includes distance calculations, unit conversion, angle conversion, and quick non-cryptographic hash helpers. LanguageHelper converts camel case identifiers into human-readable text. Core Utility Types The root CapyKit namespace includes small types that support the helpers: Password, IPasswordAlgorithm, and Pbkdf2Algorithm model password hashing. Pool<T> and PoolItem<T> provide a simple resource pool abstraction. PropertyComparer<T, U> compares objects by a selected property. CapyEventReporter, CapyEventArgs, and EventLevel expose library diagnostics without requiring a specific logging package. NamedColor provides a large named color enumeration based on the XKCD color survey palette. Design Approach CapyKit favors explicit, discoverable APIs. Most helpers are static methods or extension methods and can be adopted independently. You can use only the namespaces you need, and the library does not impose dependency injection, hosting, logging, or configuration conventions on the consuming application. Where CapyKit needs to communicate warnings or errors internally, it uses CapyEventReporter. Applications can subscribe to these events and map them into their preferred logging, telemetry, or diagnostics system. API Reference The generated API reference is available through the DocFX navigation and starts at API Reference. Use it for exact signatures, overloads, return types, exceptions, and XML comment details."
}
}

View file

@ -73,6 +73,41 @@
<article data-uid="">
<h1 id="introduction">Introduction</h1>
<p>CapyKit is a practical toolkit for .NET applications. It collects common helpers and extension methods into one package so application code can stay focused on business behavior instead of re-implementing the same plumbing in every project.</p>
<p>The project began as shared infrastructure for HappyCapy and is now available as a standalone library. It currently targets .NET 8.</p>
<h2 id="what-capykit-provides">What CapyKit Provides</h2>
<h3 id="extension-methods">Extension Methods</h3>
<p>The <code>CapyKit.Extensions</code> namespace contains helpers for common language and LINQ tasks:</p>
<ul>
<li><code>StringExtensions</code> provides fallback helpers such as <code>IfNullOrEmpty</code> and <code>IfNullOrWhiteSpace</code>.</li>
<li><code>LINQExtensions</code> adds pagination, page counts, inverted filtering, and left outer join helpers for enumerable and queryable collections.</li>
<li><code>EnumerationExtensions</code> makes enum names, numeric values, descriptions, and human-readable names easier to retrieve.</li>
<li><code>ObjectExtensions</code> copies matching writable properties from one object to another.</li>
</ul>
<h3 id="helper-classes">Helper Classes</h3>
<p>The <code>CapyKit.Helpers</code> namespace contains focused utility classes:</p>
<ul>
<li><code>SerializationHelper</code> serializes and deserializes values with <code>System.Text.Json</code>.</li>
<li><code>CompressionHelper</code> compresses serialized values with gzip and can represent compressed data as Base64.</li>
<li><code>SecurityHelper</code> creates PBKDF2 password hashes, salts, random strings, and random passwords.</li>
<li><code>KeyHelper</code> creates and validates formatted HMAC-backed keys using a caller-provided master key.</li>
<li><code>CalculationHelper</code> includes distance calculations, unit conversion, angle conversion, and quick non-cryptographic hash helpers.</li>
<li><code>LanguageHelper</code> converts camel case identifiers into human-readable text.</li>
</ul>
<h3 id="core-utility-types">Core Utility Types</h3>
<p>The root <code>CapyKit</code> namespace includes small types that support the helpers:</p>
<ul>
<li><code>Password</code>, <code>IPasswordAlgorithm</code>, and <code>Pbkdf2Algorithm</code> model password hashing.</li>
<li><code>Pool&lt;T&gt;</code> and <code>PoolItem&lt;T&gt;</code> provide a simple resource pool abstraction.</li>
<li><code>PropertyComparer&lt;T, U&gt;</code> compares objects by a selected property.</li>
<li><code>CapyEventReporter</code>, <code>CapyEventArgs</code>, and <code>EventLevel</code> expose library diagnostics without requiring a specific logging package.</li>
<li><code>NamedColor</code> provides a large named color enumeration based on the XKCD color survey palette.</li>
</ul>
<h2 id="design-approach">Design Approach</h2>
<p>CapyKit favors explicit, discoverable APIs. Most helpers are static methods or extension methods and can be adopted independently. You can use only the namespaces you need, and the library does not impose dependency injection, hosting, logging, or configuration conventions on the consuming application.</p>
<p>Where CapyKit needs to communicate warnings or errors internally, it uses <code>CapyEventReporter</code>. Applications can subscribe to these events and map them into their preferred logging, telemetry, or diagnostics system.</p>
<h2 id="api-reference">API Reference</h2>
<p>The generated API reference is available through the DocFX navigation and starts at <a href="api/toc.html">API Reference</a>. Use it for exact signatures, overloads, return types, exceptions, and XML comment details.</p>
</article>

View file

@ -18,6 +18,141 @@
<li>
<a href="getting-started.html" name="" title="Getting Started">Getting Started</a>
</li>
<li>
<span class="expand-stub"></span>
<a>API Reference</a>
<ul class="nav level2">
<li>
<span class="expand-stub"></span>
<a href="api/CapyKit.html" name="" title="CapyKit">CapyKit</a>
<ul class="nav level3">
<li>
<a href="api/CapyKit.CapyEventArgs.html" name="" title="CapyEventArgs">CapyEventArgs</a>
</li>
<li>
<a href="api/CapyKit.CapyEventHandler.html" name="" title="CapyEventHandler">CapyEventHandler</a>
</li>
<li>
<a href="api/CapyKit.CapyEventReporter.html" name="" title="CapyEventReporter">CapyEventReporter</a>
</li>
<li>
<a href="api/CapyKit.Color.html" name="" title="Color">Color</a>
</li>
<li>
<a href="api/CapyKit.EncryptedValue-1.html" name="" title="EncryptedValue&lt;T&gt;">EncryptedValue&lt;T&gt;</a>
</li>
<li>
<a href="api/CapyKit.EventLevel.html" name="" title="EventLevel">EventLevel</a>
</li>
<li>
<a href="api/CapyKit.IPasswordAlgorithm.html" name="" title="IPasswordAlgorithm">IPasswordAlgorithm</a>
</li>
<li>
<a href="api/CapyKit.NamedColor.html" name="" title="NamedColor">NamedColor</a>
</li>
<li>
<a href="api/CapyKit.Password.html" name="" title="Password">Password</a>
</li>
<li>
<a href="api/CapyKit.Pbkdf2Algorithm.html" name="" title="Pbkdf2Algorithm">Pbkdf2Algorithm</a>
</li>
<li>
<a href="api/CapyKit.PoolItem-1.html" name="" title="PoolItem&lt;T&gt;">PoolItem&lt;T&gt;</a>
</li>
<li>
<a href="api/CapyKit.Pool-1.html" name="" title="Pool&lt;T&gt;">Pool&lt;T&gt;</a>
</li>
<li>
<a href="api/CapyKit.PropertyComparer-2.html" name="" title="PropertyComparer&lt;T, U&gt;">PropertyComparer&lt;T, U&gt;</a>
</li>
</ul>
</li>
<li>
<span class="expand-stub"></span>
<a href="api/CapyKit.Attributes.html" name="" title="CapyKit.Attributes">CapyKit.Attributes</a>
<ul class="nav level3">
<li>
<a href="api/CapyKit.Attributes.EnumerationAttribute-1.html" name="" title="EnumerationAttribute&lt;T&gt;">EnumerationAttribute&lt;T&gt;</a>
</li>
<li>
<a href="api/CapyKit.Attributes.EnumerationDescriptionAttribute.html" name="" title="EnumerationDescriptionAttribute">EnumerationDescriptionAttribute</a>
</li>
<li>
<a href="api/CapyKit.Attributes.ValueFormatAttribute.html" name="" title="ValueFormatAttribute">ValueFormatAttribute</a>
</li>
</ul>
</li>
<li>
<span class="expand-stub"></span>
<a href="api/CapyKit.Enumerations.html" name="" title="CapyKit.Enumerations">CapyKit.Enumerations</a>
<ul class="nav level3">
<li>
<a href="api/CapyKit.Enumerations.MeasurementSystem.html" name="" title="MeasurementSystem">MeasurementSystem</a>
</li>
</ul>
</li>
<li>
<span class="expand-stub"></span>
<a href="api/CapyKit.Extensions.html" name="" title="CapyKit.Extensions">CapyKit.Extensions</a>
<ul class="nav level3">
<li>
<a href="api/CapyKit.Extensions.EnumerationExtensions.html" name="" title="EnumerationExtensions">EnumerationExtensions</a>
</li>
<li>
<a href="api/CapyKit.Extensions.LINQExtensions.html" name="" title="LINQExtensions">LINQExtensions</a>
</li>
<li>
<a href="api/CapyKit.Extensions.ObjectExtensions.html" name="" title="ObjectExtensions">ObjectExtensions</a>
</li>
<li>
<a href="api/CapyKit.Extensions.StringExtensions.html" name="" title="StringExtensions">StringExtensions</a>
</li>
</ul>
</li>
<li>
<span class="expand-stub"></span>
<a href="api/CapyKit.Helpers.html" name="" title="CapyKit.Helpers">CapyKit.Helpers</a>
<ul class="nav level3">
<li>
<a href="api/CapyKit.Helpers.CalculationHelper.html" name="" title="CalculationHelper">CalculationHelper</a>
</li>
<li>
<a href="api/CapyKit.Helpers.CompressionHelper.html" name="" title="CompressionHelper">CompressionHelper</a>
</li>
<li>
<a href="api/CapyKit.Helpers.EncryptionHelper.html" name="" title="EncryptionHelper">EncryptionHelper</a>
</li>
<li>
<a href="api/CapyKit.Helpers.IEncryptionAlgorithm.html" name="" title="IEncryptionAlgorithm">IEncryptionAlgorithm</a>
</li>
<li>
<a href="api/CapyKit.Helpers.KeyHelper.html" name="" title="KeyHelper">KeyHelper</a>
</li>
<li>
<a href="api/CapyKit.Helpers.LanguageHelper.html" name="" title="LanguageHelper">LanguageHelper</a>
</li>
<li>
<a href="api/CapyKit.Helpers.SecurityHelper.html" name="" title="SecurityHelper">SecurityHelper</a>
</li>
<li>
<a href="api/CapyKit.Helpers.SerializationHelper.html" name="" title="SerializationHelper">SerializationHelper</a>
</li>
<li>
<a href="api/CapyKit.Helpers.SettingsHelper.html" name="" title="SettingsHelper">SettingsHelper</a>
</li>
<li>
<a href="api/CapyKit.Helpers.ValidCharacterCollection.html" name="" title="ValidCharacterCollection">ValidCharacterCollection</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>

File diff suppressed because one or more lines are too long

View file

@ -1 +1,132 @@
# Getting Started
# Getting Started
This guide shows the common setup and first-use patterns for consuming CapyKit from a .NET 8 project.
## Install
Add CapyKit to your project from NuGet:
```bash
dotnet add package CapyKit
```
If you are working from a local checkout instead, reference the project directly:
```bash
dotnet add reference ../CapyKit/CapyKit.csproj
```
## Add Namespaces
Most APIs live in one of three namespaces:
```csharp
using CapyKit;
using CapyKit.Extensions;
using CapyKit.Helpers;
```
Use `CapyKit` for core types such as `Password`, `Pool<T>`, and `CapyEventReporter`. Use `CapyKit.Extensions` for extension methods. Use `CapyKit.Helpers` for serialization, compression, security, keys, language, and calculation helpers.
## Work With Strings
```csharp
using CapyKit.Extensions;
string? suppliedName = "";
string name = suppliedName.IfNullOrWhiteSpace("Guest");
```
`IfNullOrEmpty` and `IfNullOrWhiteSpace` return the original value when it is usable and return your replacement value when it is not.
## Page And Filter Collections
```csharp
using CapyKit.Extensions;
var activeUsers = users.Filter(user => user.Disabled);
var secondPage = activeUsers.Page(pageNumber: 2, pageSize: 25);
int pageCount = activeUsers.PageCount(pageSize: 25);
```
`Filter` removes items that match the predicate. `Page` uses natural page numbering, so the first page is `1`.
## Serialize And Compress Data
```csharp
using CapyKit.Helpers;
var json = SerializationHelper.SerializeToString(order);
var copy = SerializationHelper.Deserialize<Order>(json);
var compressed = CompressionHelper.CompressToString(order);
var restored = CompressionHelper.Decompress<Order>(compressed);
```
Serialization uses `System.Text.Json`. Compression stores the serialized JSON payload using gzip; `CompressToString` returns a Base64 representation for easier storage or transport.
## Hash And Verify Passwords
```csharp
using CapyKit;
using CapyKit.Helpers;
Password storedPassword = SecurityHelper.Pbkdf2("correct horse battery staple");
bool passwordMatches = SecurityHelper.CompareHashedPassword(
storedPassword,
"correct horse battery staple",
storedPassword.Salt,
Password.Pbkdf2Algorithm);
```
`SecurityHelper.Pbkdf2` creates a `Password` with a random salt. Store the hash, salt, and algorithm information required by your application, then compare future password attempts using the same salt and algorithm.
## Generate Random Values
```csharp
using CapyKit.Helpers;
string token = SecurityHelper.GetRandomString(32);
string password = SecurityHelper.GetRandomPassword(
20,
ValidCharacterCollection.Lowercase,
ValidCharacterCollection.Uppercase,
ValidCharacterCollection.Numbers,
ValidCharacterCollection.Special);
```
Random string and password generation use .NET cryptographic random number generation.
## Create And Validate Keys
```csharp
using System.Text;
using CapyKit.Helpers;
var keyHelper = new KeyHelper();
keyHelper.SetMasterKeyAccessor(() => Encoding.UTF8.GetBytes("replace-with-your-master-key"));
keyHelper.SetSaltSizeAccessor(() => 8);
keyHelper.SetNumPartsAccessor(() => 4);
string key = keyHelper.GenerateKey();
bool valid = keyHelper.ValidateKey(key);
```
`KeyHelper` uses an application-provided master key to sign generated key material. Keep the master key secret and stable for keys that must remain valid over time.
## Subscribe To CapyKit Events
```csharp
using CapyKit;
CapyEventReporter.Subscribe(
e => Console.WriteLine($"[{e.Level}] {e.MethodName}: {e.Message}"),
EventLevel.Warning);
```
CapyKit does not require a logging framework. Subscribe to events and forward them to whatever logging or telemetry system your application already uses.
## Browse The API
For the full list of namespaces, types, overloads, and member signatures, open the generated [API Reference](api/toc.yml).

View file

@ -1,11 +1,79 @@
---
_layout: landing
---
# This is the **HOMEPAGE**.
Refer to [Markdown](http://daringfireball.net/projects/markdown/) for how to write markdown files.
## Quick Start Notes:
1. Add images to the *images* folder if the file is referencing an image.
---
_layout: landing
---
# CapyKit Documentation
CapyKit is a small .NET utility library for the code you end up writing repeatedly: collection helpers, string and enum extensions, JSON serialization, gzip compression, password hashing, random token generation, simple key validation, distance calculations, and lightweight event reporting.
The library targets .NET 8 and keeps its public surface intentionally direct. Most features are static helpers or extension methods, so consuming projects can adopt one piece at a time without taking on a framework or application model.
## Start Here
- [Introduction](introduction.md) explains what CapyKit includes and how the namespaces are organized.
- [Getting Started](getting-started.md) shows installation, imports, and common usage examples.
- [API Reference](api/toc.yml) contains the generated DocFX reference for every public type and member.
## Common Tasks
### Work with strings and collections
Use `CapyKit.Extensions` for small quality-of-life helpers such as null fallback values, pagination, inverted filtering, left outer joins, enum display names, and property copying.
```csharp
using CapyKit.Extensions;
var displayName = user.Name.IfNullOrWhiteSpace("Guest");
var page = users.Page(pageNumber: 2, pageSize: 25);
```
### Serialize, compress, and restore values
Use `CapyKit.Helpers.SerializationHelper` and `CapyKit.Helpers.CompressionHelper` when you need straightforward JSON serialization or gzip compression around serializable values.
```csharp
using CapyKit.Helpers;
var payload = SerializationHelper.SerializeToString(order);
var compressed = CompressionHelper.CompressToString(order);
var restored = CompressionHelper.Decompress<Order>(compressed);
```
### Hash passwords and generate tokens
Use `SecurityHelper` for PBKDF2 password hashes, salts, and random values backed by .NET cryptographic random number generation.
```csharp
using CapyKit;
using CapyKit.Helpers;
Password password = SecurityHelper.Pbkdf2("correct horse battery staple");
bool matches = SecurityHelper.CompareHashedPassword(
password,
"correct horse battery staple",
password.Salt,
Password.Pbkdf2Algorithm);
```
### Listen to CapyKit events
CapyKit reports warnings and errors through `CapyEventReporter` instead of choosing a logging framework for you. Subscribe at the level your application cares about and route events into your own logging pipeline.
```csharp
using CapyKit;
CapyEventReporter.Subscribe(
e => logger.LogWarning("{Method}: {Message}", e.MethodName, e.Message),
EventLevel.Warning);
```
## Build The Docs Locally
The documentation is generated with DocFX from the Markdown files in this folder and the XML comments in the `CapyKit` project.
```bash
dotnet tool install -g docfx
docfx Docs/docfx.json --serve
```
DocFX writes the generated site to `Docs/_site`.

View file

@ -1 +1,47 @@
# Introduction
# Introduction
CapyKit is a practical toolkit for .NET applications. It collects common helpers and extension methods into one package so application code can stay focused on business behavior instead of re-implementing the same plumbing in every project.
The project began as shared infrastructure for HappyCapy and is now available as a standalone library. It currently targets .NET 8.
## What CapyKit Provides
### Extension Methods
The `CapyKit.Extensions` namespace contains helpers for common language and LINQ tasks:
- `StringExtensions` provides fallback helpers such as `IfNullOrEmpty` and `IfNullOrWhiteSpace`.
- `LINQExtensions` adds pagination, page counts, inverted filtering, and left outer join helpers for enumerable and queryable collections.
- `EnumerationExtensions` makes enum names, numeric values, descriptions, and human-readable names easier to retrieve.
- `ObjectExtensions` copies matching writable properties from one object to another.
### Helper Classes
The `CapyKit.Helpers` namespace contains focused utility classes:
- `SerializationHelper` serializes and deserializes values with `System.Text.Json`.
- `CompressionHelper` compresses serialized values with gzip and can represent compressed data as Base64.
- `SecurityHelper` creates PBKDF2 password hashes, salts, random strings, and random passwords.
- `KeyHelper` creates and validates formatted HMAC-backed keys using a caller-provided master key.
- `CalculationHelper` includes distance calculations, unit conversion, angle conversion, and quick non-cryptographic hash helpers.
- `LanguageHelper` converts camel case identifiers into human-readable text.
### Core Utility Types
The root `CapyKit` namespace includes small types that support the helpers:
- `Password`, `IPasswordAlgorithm`, and `Pbkdf2Algorithm` model password hashing.
- `Pool<T>` and `PoolItem<T>` provide a simple resource pool abstraction.
- `PropertyComparer<T, U>` compares objects by a selected property.
- `CapyEventReporter`, `CapyEventArgs`, and `EventLevel` expose library diagnostics without requiring a specific logging package.
- `NamedColor` provides a large named color enumeration based on the XKCD color survey palette.
## Design Approach
CapyKit favors explicit, discoverable APIs. Most helpers are static methods or extension methods and can be adopted independently. You can use only the namespaces you need, and the library does not impose dependency injection, hosting, logging, or configuration conventions on the consuming application.
Where CapyKit needs to communicate warnings or errors internally, it uses `CapyEventReporter`. Applications can subscribe to these events and map them into their preferred logging, telemetry, or diagnostics system.
## API Reference
The generated API reference is available through the DocFX navigation and starts at [API Reference](api/toc.yml). Use it for exact signatures, overloads, return types, exceptions, and XML comment details.

View file

@ -1,4 +1,6 @@
- name: Introduction
href: introduction.md
- name: Getting Started
href: getting-started.md
- name: Introduction
href: introduction.md
- name: Getting Started
href: getting-started.md
- name: API Reference
href: api/toc.yml

View file

@ -1,10 +1,67 @@
# CapyKit
A versatile collection of C# utilities and extensions designed to supercharge any .NET project. Born from the HappyCapy project, now open for the community.
CapyKit is a practical .NET utility library for the small pieces of application code that tend to get rewritten from project to project. It includes focused helpers for strings, collections, serialization, compression, password hashing, random value generation, key validation, calculations, resource pooling, and lightweight library diagnostics.
The project started as shared infrastructure for HappyCapy and is now packaged as a standalone toolkit for .NET 8 applications.
## What Is Included
- Extension methods for strings, enums, objects, and LINQ collections.
- JSON serialization and gzip compression helpers.
- PBKDF2 password hashing, salt generation, and random token/password generation.
- HMAC-backed formatted key generation and validation.
- Distance, unit conversion, angle conversion, and quick hash helpers.
- A simple resource pool abstraction.
- `CapyEventReporter` for routing CapyKit warnings and errors into your own logging system.
- A generated DocFX API reference for the public surface area.
## Install
```bash
dotnet add package CapyKit
```
For local development from this repository:
```bash
dotnet add reference ./CapyKit/CapyKit.csproj
```
## Quick Example
```csharp
using CapyKit;
using CapyKit.Extensions;
using CapyKit.Helpers;
var name = incomingName.IfNullOrWhiteSpace("Guest");
var page = users.Page(pageNumber: 1, pageSize: 25);
Password password = SecurityHelper.Pbkdf2("correct horse battery staple");
bool matches = SecurityHelper.CompareHashedPassword(
password,
"correct horse battery staple",
password.Salt,
Password.Pbkdf2Algorithm);
```
## Documentation
You can find an early version of the automatically generated documentation [here](./Documentation/Help/Home.md).
The in-repository documentation starts at [Docs/index.md](Docs/index.md). It includes an introduction, getting-started guide, and links into the generated DocFX API reference.
## TODO
To build and serve the documentation locally:
Obviously this repository is in pretty rough shape right now while I make the full transition from the private repository to this one. Please bear with me. :)
```bash
dotnet tool install -g docfx
docfx Docs/docfx.json --serve
```
DocFX writes the generated site to `Docs/_site`.
## Project Status
CapyKit is a growing utility library. Some APIs are mature and covered by tests, while others are still being rounded out as the project transitions from private shared code into a public package. Review the generated API reference and tests when adopting a helper in production code.
## License
This project is licensed under the terms in [LICENSE](LICENSE).