Husky.Net brings the dev-dependency concept to the .NET ecosystem.
You can attach husky to your project without adding extra dependencies! This way the other contributors will use your pre-configured tasks automatically.
To manually attach husky to your project, add the below code to one of your projects (.csproj/.vbproj).
<TargetName="husky"BeforeTargets="Restore;CollectPackageReferences"Condition="'$(HUSKY)' != 0">
+ <ExecCommand="dotnet tool restore"StandardOutputImportance="Low"StandardErrorImportance="High"/>
+ <ExecCommand="dotnet husky install"StandardOutputImportance="Low"StandardErrorImportance="High"
+ WorkingDirectory="../../"/><!--Update this to the relative path to your project root dir -->
+</Target>
+
TIP
Make sure to update the working directory depending on your folder structure it should be a relative path to your project root dir
WARNING
Adding the above code to a multiple targeted project will cause husky to run multiple times. e.g <TargetFrameworks>netcoreapp3.1;net5.0;net6.0;net7.0</TargetFrameworks>
to avoid this, you can add the $(IsCrossTargetingBuild)' == 'true' condition to the target. e.g
<TargetName="husky"BeforeTargets="Restore;CollectPackageReferences"Condition="'$(HUSKY)' != 0 and '$(IsCrossTargetingBuild)' == 'true'">
+...
+
`,18);function e(o,p){return s}var l=n(t,[["render",e]]);export{l as default};
diff --git a/assets/back-to-top.8efcbe56.svg b/assets/back-to-top.8efcbe56.svg
new file mode 100644
index 0000000..8323678
--- /dev/null
+++ b/assets/back-to-top.8efcbe56.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/csharp-script.html.66921e8d.js b/assets/csharp-script.html.66921e8d.js
new file mode 100644
index 0000000..076490b
--- /dev/null
+++ b/assets/csharp-script.html.66921e8d.js
@@ -0,0 +1 @@
+const e={key:"v-44c2d174",path:"/guide/csharp-script.html",title:"Using C# code in your git hooks",lang:"en-US",frontmatter:{},excerpt:"",headers:[{level:2,title:"Examples",slug:"examples",children:[{level:3,title:"Simple commit message linter",slug:"simple-commit-message-linter",children:[]}]}],git:{updatedTime:1641528435e3},filePathRelative:"guide/csharp-script.md"};export{e as data};
diff --git a/assets/csharp-script.html.b6baa528.js b/assets/csharp-script.html.b6baa528.js
new file mode 100644
index 0000000..c9e999f
--- /dev/null
+++ b/assets/csharp-script.html.b6baa528.js
@@ -0,0 +1,37 @@
+import{r as p,o,c,b as s,a as e,F as l,d as n,e as t}from"./app.22727b9e.js";import{_ as r}from"./plugin-vue_export-helper.21dcd24c.js";const u={},i=n(`
`,1);function v(f,C){const a=p("ExternalLinkIcon");return o(),c(l,null,[i,s("p",null,[s("a",k,[m,e(a)])]),b,s("p",null,[s("a",d,[h,g,e(a)])]),q,s("p",null,[s("a",x,[y,e(a)])]),_],64)}var N=r(u,[["render",v]]);export{N as default};
diff --git a/assets/getting-started.html.640b3ed8.js b/assets/getting-started.html.640b3ed8.js
new file mode 100644
index 0000000..7454553
--- /dev/null
+++ b/assets/getting-started.html.640b3ed8.js
@@ -0,0 +1,11 @@
+import{r as s,o as l,c as i,b as e,a as t,w as o,F as d,e as a,d as p}from"./app.22727b9e.js";import{_ as u}from"./plugin-vue_export-helper.21dcd24c.js";const h={},m=e("h1",{id:"getting-started",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#getting-started","aria-hidden":"true"},"#"),a(" Getting Started")],-1),g=e("p",null,"Husky.Net is a dotnet tool available in nuget repository.",-1),k={href:"https://www.nuget.org/packages/Husky/",target:"_blank",rel:"noopener noreferrer"},_=a("Husky"),f=e("h2",{id:"installation",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#installation","aria-hidden":"true"},"#"),a(" Installation")],-1),y=e("div",{class:"language-bash ext-sh"},[e("pre",{class:"language-bash"},[e("code",null,[e("span",{class:"token builtin class-name"},"cd"),a(),e("span",{class:"token operator"},"<"),a("Your project root directory"),e("span",{class:"token operator"},">"),a(`
+dotnet new tool-manifest
+dotnet tool `),e("span",{class:"token function"},"install"),a(` Husky
+`)])])],-1),b=e("div",{class:"language-bash ext-sh"},[e("pre",{class:"language-bash"},[e("code",null,[a("dotnet tool "),e("span",{class:"token function"},"install"),a(` --global Husky
+`)])])],-1),x=p(`
git commit -m "Keep calm and commit"
+# \`echo 'Husky.Net is awesome!'\` will run every time you commit
+
`,7);function v(w,j){const c=s("ExternalLinkIcon"),n=s("CodeGroupItem"),r=s("CodeGroup");return l(),i(d,null,[m,g,e("ul",null,[e("li",null,[e("a",k,[_,t(c)])])]),f,t(r,null,{default:o(()=>[t(n,{title:"local (recommended)"},{default:o(()=>[y]),_:1}),t(n,{title:"global"},{default:o(()=>[b]),_:1})]),_:1}),x],64)}var C=u(h,[["render",v]]);export{C as default};
diff --git a/assets/getting-started.html.a51a07e5.js b/assets/getting-started.html.a51a07e5.js
new file mode 100644
index 0000000..a4f0bf7
--- /dev/null
+++ b/assets/getting-started.html.a51a07e5.js
@@ -0,0 +1 @@
+const t={key:"v-fb0f0066",path:"/guide/getting-started.html",title:"Getting Started",lang:"en-US",frontmatter:{},excerpt:"",headers:[{level:2,title:"Installation",slug:"installation",children:[]},{level:2,title:"Setup husky for your project",slug:"setup-husky-for-your-project",children:[]},{level:2,title:"Add your first hook",slug:"add-your-first-hook",children:[]},{level:2,title:"Make a commit",slug:"make-a-commit",children:[]}],git:{updatedTime:1641474529e3},filePathRelative:"guide/getting-started.md"};export{t as data};
diff --git a/assets/index.html.2aaa5aee.js b/assets/index.html.2aaa5aee.js
new file mode 100644
index 0000000..cab67b3
--- /dev/null
+++ b/assets/index.html.2aaa5aee.js
@@ -0,0 +1,5 @@
+import{r,o as c,c as l,a as t,w as a,b as e,F as d,d as u,e as o}from"./app.22727b9e.js";import{_ as h}from"./plugin-vue_export-helper.21dcd24c.js";const _={},p=u('
Husky.Net documentation is powered by vuePress, All the markdown source files are placed in docs directory.
by running the following commands, you can run the documentation site locally:
',8),m=e("div",{class:"language-cmd ext-cmd line-numbers-mode"},[e("pre",{class:"language-cmd"},[e("code",null,`yarn install
+yarn dev
+`)]),e("div",{class:"line-numbers"},[e("span",{class:"line-number"},"1"),e("br"),e("span",{class:"line-number"},"2"),e("br")])],-1),b=e("div",{class:"language-cmd ext-cmd line-numbers-mode"},[e("pre",{class:"language-cmd"},[e("code",null,`npm install
+npm run dev
+`)]),e("div",{class:"line-numbers"},[e("span",{class:"line-number"},"1"),e("br"),e("span",{class:"line-number"},"2"),e("br")])],-1),f=e("h2",{id:"how-to-contribute",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#how-to-contribute","aria-hidden":"true"},"#"),o(" How to contribute")],-1),g=o("check out the "),x={href:"https://git-scm.com/book/en/v2/GitHub-Contributing-to-a-Project",target:"_blank",rel:"noopener noreferrer"},k=o("github contributing guide"),y=e("h2",{id:"contributors",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#contributors","aria-hidden":"true"},"#"),o(" Contributors")],-1),v={href:"https://github.com/alirezanet",target:"_blank",rel:"noopener noreferrer"},j=o("AliReZa Sabouri"),w={href:"https://github.com/SajjadHosseinPour",target:"_blank",rel:"noopener noreferrer"},C=o("Sajjad Hossein Pour"),A={href:"https://github.com/atifaziz",target:"_blank",rel:"noopener noreferrer"},z=o("Atif Aziz"),G={href:"https://github.com/acesyde",target:"_blank",rel:"noopener noreferrer"},H=o("Pierre Mercier"),I=e("li",null,"Add your name",-1);function N(P,S){const s=r("CodeGroupItem"),i=r("CodeGroup"),n=r("ExternalLinkIcon");return c(),l(d,null,[p,t(i,null,{default:a(()=>[t(s,{title:"yarn"},{default:a(()=>[m]),_:1}),t(s,{title:"npm"},{default:a(()=>[b]),_:1})]),_:1}),f,e("p",null,[g,e("a",x,[k,t(n)])]),y,e("ul",null,[e("li",null,[e("a",v,[j,t(n)])]),e("li",null,[e("a",w,[C,t(n)])]),e("li",null,[e("a",A,[z,t(n)])]),e("li",null,[e("a",G,[H,t(n)])]),I])],64)}var E=h(_,[["render",N]]);export{E as default};
diff --git a/assets/index.html.504c7800.js b/assets/index.html.504c7800.js
new file mode 100644
index 0000000..8fe03b2
--- /dev/null
+++ b/assets/index.html.504c7800.js
@@ -0,0 +1 @@
+import{_ as e}from"./plugin-vue_export-helper.21dcd24c.js";const r={};function _(c,n){return null}var o=e(r,[["render",_]]);export{o as default};
diff --git a/assets/index.html.56e1725b.js b/assets/index.html.56e1725b.js
new file mode 100644
index 0000000..5c56b23
--- /dev/null
+++ b/assets/index.html.56e1725b.js
@@ -0,0 +1 @@
+import{r as n,o as r,c as a,b as e,a as s,F as i,e as o}from"./app.22727b9e.js";import{_ as l}from"./plugin-vue_export-helper.21dcd24c.js";var d="/Husky.Net/assets/workflow.290a20c9.jpg";const c={},h=e("h1",{id:"introduction",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#introduction","aria-hidden":"true"},"#"),o(" Introduction")],-1),u=e("p",null,[e("img",{src:d,alt:"Husky.Net WorkFlow"})],-1),_=e("blockquote",null,[e("p",null,"Husky improves your commits and more \u{1F436} woof!"),e("p",null,"Run linters against staged git files and don't let \u{1F4A9} slip into your code base!")],-1),m=o("These two quotes from "),p={href:"https://github.com/typicode/husky",target:"_blank",rel:"noopener noreferrer"},f=o("husky"),y=o(" and "),k={href:"https://github.com/okonet/lint-staged",target:"_blank",rel:"noopener noreferrer"},g=o("lint-staged"),b=o(" JS tools inspired me to create Husky.Net for dotnet developers. it provides a simple native way to do both also has a lot of other cool features, You can use it to lint your commit messages, run tests, lint/format code, etc... when you commit or push. \u{1F680}\u{1F680}"),w=e("h2",{id:"features",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#features","aria-hidden":"true"},"#"),o(" Features")],-1),v=e("li",null,[o("\u{1F525} It brings the "),e("strong",null,"dev-dependency"),o(" concept to the .NET world!")],-1),x=e("li",null,"\u{1F525} Supports all Git & gitflow hooks",-1),N=e("li",null,"\u{1F525} Internal task runner!",-1),S=e("li",null,"Multiple file states (staged, last-commit, git-files, etc...)",-1),H=e("li",null,"CSharp scripts (csx)",-1),I=e("li",null,"Supports macOS, Linux and Windows",-1),C=e("li",null,"Powered by modern new Git feature (core.hooksPath)",-1),T=e("li",null,"User-define variables",-1),G=o("Compatible with "),j={href:"https://github.com/dotnet/format",target:"_blank",rel:"noopener noreferrer"},L=o("dotnet-format"),W=o(", "),E={href:"https://csharpier.com/",target:"_blank",rel:"noopener noreferrer"},F=o("CSharpier"),A=o(", "),B={href:"https://www.jetbrains.com/help/resharper/ReSharper_Command_Line_Tools.html",target:"_blank",rel:"noopener noreferrer"},R=o("ReSharper command line tools"),U=o(" and other formatting tools"),V=e("li",null,"User-friendly messages",-1),q=e("li",null,"Git GUIs",-1),D=e("li",null,"Custom directories",-1),M=e("li",null,"Monorepo",-1),O=e("p",null,[o("-"),e("em",null,"A lot of features are coming soon, stay tuned! \u{1F441}\uFE0F\u200D\u{1F5E8}\uFE0F\u{1F440}")],-1),P=e("h2",{id:"why-use-hooks-and-husky-net",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#why-use-hooks-and-husky-net","aria-hidden":"true"},"#"),o(" Why use Hooks and Husky.Net?")],-1),Y=e("p",null,"We, as developers, love platforms like GitHub, GitLab, Atlassian, Azure DevOps etc., as our managed git system and collaboration platform. We also love clean code and keep inventing new linters and rules to enforce it. In my opinion, every commit should allow the codebase to deploy to production. There is nothing worse than commits like \u201Cfixed style errors\u201D or \u201Cfixed build\u201D. These are often small mistakes you want to know as early as possible in your development cycle. You don\u2019t want to break the build for the next developer because he pulled your \u2018mistake\u2019 or waste precious build minutes of your CI server. Say you have asked your teammate to review your code; in the meantime, the build server rejects your code. That means you have to go back and fix this, and your teammate has to come back and possibly review again after the changes (i.e., approvals reset on new commit). Doing so would waste a lot of time and effort.",-1),z=e("p",null,"Husky.Net offers a very simple way to start using git hooks or running certain tasks, write and run custom scripts and more ...",-1);function J(K,Q){const t=n("ExternalLinkIcon");return r(),a(i,null,[h,u,_,e("p",null,[m,e("a",p,[f,s(t)]),y,e("a",k,[g,s(t)]),b]),w,e("ul",null,[v,x,N,S,H,I,C,T,e("li",null,[G,e("a",j,[L,s(t)]),W,e("a",E,[F,s(t)]),A,e("a",B,[R,s(t)]),U]),V,q,D,M]),O,P,Y,z],64)}var $=l(c,[["render",J]]);export{$ as default};
diff --git a/assets/index.html.710bbd8d.js b/assets/index.html.710bbd8d.js
new file mode 100644
index 0000000..01595a2
--- /dev/null
+++ b/assets/index.html.710bbd8d.js
@@ -0,0 +1 @@
+const t={key:"v-42d847c6",path:"/contribution/",title:"Contribute to the project",lang:"en-US",frontmatter:{},excerpt:"",headers:[{level:2,title:"Todos",slug:"todos",children:[]},{level:2,title:"Documentation",slug:"documentation",children:[]},{level:2,title:"How to contribute",slug:"how-to-contribute",children:[]},{level:2,title:"Contributors",slug:"contributors",children:[]}],git:{updatedTime:1673097895e3},filePathRelative:"contribution/README.md"};export{t as data};
diff --git a/assets/index.html.80ef201c.js b/assets/index.html.80ef201c.js
new file mode 100644
index 0000000..e1f945e
--- /dev/null
+++ b/assets/index.html.80ef201c.js
@@ -0,0 +1 @@
+const t={key:"v-8daa1a0e",path:"/",title:"Welcome",lang:"en-US",frontmatter:{home:!0,title:"Welcome",tagline:"It brings the dev-dependency concept to the .NET world!",actions:[{text:"Get Started",link:"/guide/getting-started.md",type:"primary"},{text:"Introduction",link:"/guide/",type:"secondary"}],features:[{title:"Easy To Use",details:"Just with a few commands you can start using the git hooks to keep your code clean and organized."},{title:"Git hooks",details:"Supports all git and git-flow hooks, powered by modern git features."},{title:"Task Runner",details:"Has a powerful task runner that you can use to manage and run linters, tests, scripts, and more."},{title:"Automate for everyone",details:"You can configure it to automatically run your tasks when other contributors work with your repository."},{title:"Multiple File States",details:"Supports multiple file states like staged, last-commit, git-files, etc, and user-defined states."},{title:"CSharp Script",details:"Supports C# scripting for more complex tasks."}],footer:"MIT Licensed | Copyright \xA9 2022-present AliReZa Sabouri"},excerpt:"",headers:[],git:{updatedTime:1642251873e3},filePathRelative:"README.md"};export{t as data};
diff --git a/assets/index.html.c4b28ab0.js b/assets/index.html.c4b28ab0.js
new file mode 100644
index 0000000..4c8d3fe
--- /dev/null
+++ b/assets/index.html.c4b28ab0.js
@@ -0,0 +1 @@
+const e={key:"v-fffb8e28",path:"/guide/",title:"Introduction",lang:"en-US",frontmatter:{},excerpt:"",headers:[{level:2,title:"Features",slug:"features",children:[]},{level:2,title:"Why use Hooks and Husky.Net?",slug:"why-use-hooks-and-husky-net",children:[]}],git:{updatedTime:1680598084e3},filePathRelative:"guide/README.md"};export{e as data};
diff --git a/assets/plugin-vue_export-helper.21dcd24c.js b/assets/plugin-vue_export-helper.21dcd24c.js
new file mode 100644
index 0000000..aae20ad
--- /dev/null
+++ b/assets/plugin-vue_export-helper.21dcd24c.js
@@ -0,0 +1 @@
+var a=(t,o)=>{const r=t.__vccOpts||t;for(const[e,_]of o)r[e]=_;return r};export{a as _};
diff --git a/assets/search.0782d0d1.svg b/assets/search.0782d0d1.svg
new file mode 100644
index 0000000..03d8391
--- /dev/null
+++ b/assets/search.0782d0d1.svg
@@ -0,0 +1 @@
+
diff --git a/assets/style.217a916a.css b/assets/style.217a916a.css
new file mode 100644
index 0000000..fbc4595
--- /dev/null
+++ b/assets/style.217a916a.css
@@ -0,0 +1 @@
+:root{--external-link-icon-color:#aaa}.external-link-icon{position:relative;display:inline-block;color:var(--external-link-icon-color);vertical-align:middle;top:-1px}:root{--medium-zoom-z-index:100;--medium-zoom-bg-color:#ffffff;--medium-zoom-opacity:1}.medium-zoom-overlay{background-color:var(--medium-zoom-bg-color)!important;z-index:var(--medium-zoom-z-index)}.medium-zoom-overlay~img{z-index:calc(var(--medium-zoom-z-index) + 1)}.medium-zoom--opened .medium-zoom-overlay{opacity:var(--medium-zoom-opacity)}:root{--c-brand:#3eaf7c;--c-brand-light:#4abf8a;--c-bg:#ffffff;--c-bg-light:#f3f4f5;--c-bg-lighter:#eeeeee;--c-bg-navbar:var(--c-bg);--c-bg-sidebar:var(--c-bg);--c-bg-arrow:#cccccc;--c-text:#2c3e50;--c-text-accent:var(--c-brand);--c-text-light:#3a5169;--c-text-lighter:#4e6e8e;--c-text-lightest:#6a8bad;--c-text-quote:#999999;--c-border:#eaecef;--c-border-dark:#dfe2e5;--c-tip:#42b983;--c-tip-bg:var(--c-bg-light);--c-tip-title:var(--c-text);--c-tip-text:var(--c-text);--c-tip-text-accent:var(--c-text-accent);--c-warning:#e7c000;--c-warning-bg:#fffae3;--c-warning-title:#ad9000;--c-warning-text:#746000;--c-warning-text-accent:var(--c-text);--c-danger:#cc0000;--c-danger-bg:#ffe0e0;--c-danger-title:#990000;--c-danger-text:#660000;--c-danger-text-accent:var(--c-text);--c-details-bg:#eeeeee;--c-badge-tip:var(--c-tip);--c-badge-warning:var(--c-warning);--c-badge-danger:var(--c-danger);--t-color:.3s ease;--t-transform:.3s ease;--code-bg-color:#282c34;--code-hl-bg-color:rgba(0, 0, 0, .66);--code-ln-color:#9e9e9e;--code-ln-wrapper-width:3.5rem;--font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;--font-family-code:Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;--navbar-height:3.6rem;--navbar-padding-v:.7rem;--navbar-padding-h:1.5rem;--sidebar-width:20rem;--sidebar-width-mobile:calc(var(--sidebar-width) * .82);--content-width:740px;--homepage-width:960px}.back-to-top{--back-to-top-color:var(--c-brand);--back-to-top-color-hover:var(--c-brand-light)}.DocSearch{--docsearch-primary-color:var(--c-brand);--docsearch-text-color:var(--c-text);--docsearch-highlight-color:var(--c-brand);--docsearch-muted-color:var(--c-text-quote);--docsearch-container-background:rgba(9, 10, 17, .8);--docsearch-modal-background:var(--c-bg-light);--docsearch-searchbox-background:var(--c-bg-lighter);--docsearch-searchbox-focus-background:var(--c-bg);--docsearch-searchbox-shadow:inset 0 0 0 2px var(--c-brand);--docsearch-hit-color:var(--c-text-light);--docsearch-hit-active-color:var(--c-bg);--docsearch-hit-background:var(--c-bg);--docsearch-hit-shadow:0 1px 3px 0 var(--c-border-dark);--docsearch-footer-background:var(--c-bg)}.external-link-icon{--external-link-icon-color:var(--c-text-quote)}.medium-zoom-overlay{--medium-zoom-bg-color:var(--c-bg)}#nprogress{--nprogress-color:var(--c-brand)}.pwa-popup{--pwa-popup-text-color:var(--c-text);--pwa-popup-bg-color:var(--c-bg);--pwa-popup-border-color:var(--c-brand);--pwa-popup-shadow:0 4px 16px var(--c-brand);--pwa-popup-btn-text-color:var(--c-bg);--pwa-popup-btn-bg-color:var(--c-brand);--pwa-popup-btn-hover-bg-color:var(--c-brand-light)}.search-box{--search-bg-color:var(--c-bg);--search-accent-color:var(--c-brand);--search-text-color:var(--c-text);--search-border-color:var(--c-border);--search-item-text-color:var(--c-text-lighter);--search-item-focus-bg-color:var(--c-bg-light)}html.dark{--c-brand:#3aa675;--c-brand-light:#349469;--c-bg:#22272e;--c-bg-light:#2b313a;--c-bg-lighter:#262c34;--c-text:#adbac7;--c-text-light:#96a7b7;--c-text-lighter:#8b9eb0;--c-text-lightest:#8094a8;--c-border:#3e4c5a;--c-border-dark:#34404c;--c-tip:#318a62;--c-warning:#ceab00;--c-warning-bg:#7e755b;--c-warning-title:#ceac03;--c-warning-text:#362e00;--c-danger:#940000;--c-danger-bg:#806161;--c-danger-title:#610000;--c-danger-text:#3a0000;--c-details-bg:#323843;--code-hl-bg-color:#363b46;color-scheme:dark}html.dark .DocSearch{--docsearch-logo-color:var(--c-text);--docsearch-modal-shadow:inset 1px 1px 0 0 #2c2e40, 0 3px 8px 0 #000309;--docsearch-key-shadow:inset 0 -2px 0 0 #282d55, inset 0 0 1px 1px #51577d, 0 2px 2px 0 rgba(3, 4, 9, .3);--docsearch-key-gradient:linear-gradient(-225deg, #444950, #1c1e21);--docsearch-footer-shadow:inset 0 1px 0 0 rgba(73, 76, 106, .5), 0 -4px 8px 0 rgba(0, 0, 0, .2)}body,html{padding:0;margin:0;background-color:var(--c-bg);transition:background-color var(--t-color)}body{font-family:var(--font-family);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:16px}a,p a code{color:var(--c-text-accent)}a{font-weight:500;text-decoration:none;overflow-wrap:break-word}p a code{font-weight:400}code,kbd{font-family:var(--font-family-code)}body,kbd{color:var(--c-text)}kbd{background:var(--c-bg-lighter);border:solid .15rem var(--c-border-dark);border-bottom:solid .25rem var(--c-border-dark);border-radius:.15rem;padding:0 .15em}code{color:var(--c-text-lighter);padding:.25rem .5rem;font-size:.85em;background-color:var(--c-bg-light);border-radius:3px;overflow-wrap:break-word;transition:background-color var(--t-color),color var(--t-color)}blockquote{font-size:1rem;color:var(--c-text-quote);border-left:.2rem solid var(--c-border-dark);margin:1rem 0;padding:.25rem 0 .25rem 1rem}blockquote>p,code{margin:0}ol,ul{padding-left:1.2em}strong{font-weight:600}h1,h2,h3,h4,h5,h6{font-weight:600;line-height:1.25}h1:focus-visible,h2:focus-visible,h3:focus-visible,h4:focus-visible,h5:focus-visible,h6:focus-visible{outline:0}h1:hover .header-anchor,h2:hover .header-anchor,h3:hover .header-anchor,h4:hover .header-anchor,h5:hover .header-anchor,h6:hover .header-anchor{opacity:1}h1{font-size:2.2rem}h2{font-size:1.65rem;padding-bottom:.3rem;border-bottom:1px solid var(--c-border);transition:border-color var(--t-color)}h3{font-size:1.35rem}h4{font-size:1.15rem}h5{font-size:1.05rem}h6{font-size:1rem}a.header-anchor{font-size:.85em;float:left;margin-left:-.87em;padding-right:.23em;margin-top:.125em;opacity:0}a.header-anchor:hover{text-decoration:none}a.header-anchor:focus-visible{opacity:1}ol,p,ul{line-height:1.7}hr{border:0;border-top:1px solid var(--c-border)}table{border-collapse:collapse;margin:1rem 0;display:block;overflow-x:auto}tr{border-top:1px solid var(--c-border-dark)}tr:nth-child(2n){background-color:var(--c-bg-light)}td,th{border:1px solid var(--c-border-dark);padding:.6em 1em}.arrow,.badge{display:inline-block}.arrow{width:0;height:0}.arrow.down,.arrow.up{border-left:4px solid transparent;border-right:4px solid transparent}.arrow.up{border-bottom:6px solid var(--c-bg-arrow)}.arrow.down{border-top:6px solid var(--c-bg-arrow)}.arrow.left,.arrow.right{border-top:4px solid transparent;border-bottom:4px solid transparent}.arrow.right{border-left:6px solid var(--c-bg-arrow)}.arrow.left{border-right:6px solid var(--c-bg-arrow)}.badge{font-size:14px;height:18px;line-height:18px;border-radius:3px;padding:0 6px;color:var(--c-bg);vertical-align:top;transition:color var(--t-color),background-color var(--t-color)}.badge.tip{background-color:var(--c-badge-tip)}.badge.warning{background-color:var(--c-badge-warning)}.badge.danger{background-color:var(--c-badge-danger)}.badge+.badge{margin-left:5px}code[class*=language-],pre[class*=language-]{color:#ccc;background:0 0;font-family:var(--font-family-code);font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#2d2d2d}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.block-comment,.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#999}.token.punctuation{color:#ccc}.token.attr-name,.token.deleted,.token.namespace,.token.tag{color:#ec5975}.token.function-name{color:#6196cc}.token.boolean,.token.function,.token.number{color:#f08d49}.token.class-name,.token.constant,.token.property,.token.symbol{color:#f8c555}.token.atrule,.token.builtin,.token.important,.token.keyword,.token.selector{color:#cc99cd}.token.attr-value,.token.char,.token.regex,.token.string,.token.variable{color:#7ec699}.token.entity,.token.operator,.token.url{color:#67cdcc}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:#3eaf7c}.theme-default-content pre,.theme-default-content pre[class*=language-]{line-height:1.4;padding:1.3rem 1.5rem;margin:.85rem 0;border-radius:6px;overflow:auto}.theme-default-content pre code,.theme-default-content pre[class*=language-] code{color:#fff;padding:0;background-color:transparent;border-radius:0;overflow-wrap:unset;-webkit-font-smoothing:auto;-moz-osx-font-smoothing:auto}.theme-default-content .line-number{font-family:var(--font-family-code)}div[class*=language-]{position:relative;background-color:var(--code-bg-color);border-radius:6px}div[class*=language-]:before{position:absolute;z-index:3;top:.8em;right:1em;font-size:.75rem;color:var(--code-ln-color)}div[class*=language-] pre,div[class*=language-] pre[class*=language-]{background:0 0!important;position:relative;z-index:1}div[class*=language-] .highlight-lines{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding-top:1.3rem;position:absolute;top:0;left:0;width:100%;line-height:1.4}div[class*=language-] .highlight-lines .highlight-line{background-color:var(--code-hl-bg-color)}div[class*=language-]:not(.line-numbers-mode) .line-numbers{display:none}div[class*=language-].line-numbers-mode .highlight-lines .highlight-line{position:relative}div[class*=language-].line-numbers-mode .highlight-lines .highlight-line:before{content:" ";position:absolute;z-index:2;left:0;top:0;display:block;width:var(--code-ln-wrapper-width);height:100%}div[class*=language-].line-numbers-mode pre{margin-left:var(--code-ln-wrapper-width);padding-left:1rem;vertical-align:middle}div[class*=language-].line-numbers-mode .line-numbers{position:absolute;top:0;width:var(--code-ln-wrapper-width);text-align:center;color:var(--code-ln-color);padding-top:1.25rem;line-height:1.4}div[class*=language-].line-numbers-mode .line-numbers .line-number,div[class*=language-].line-numbers-mode .line-numbers br{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}div[class*=language-].line-numbers-mode .line-numbers .line-number{position:relative;z-index:3;font-size:.85em;line-height:0}div[class*=language-].line-numbers-mode:after{content:"";position:absolute;top:0;left:0;width:var(--code-ln-wrapper-width);height:100%;border-radius:6px 0 0 6px;border-right:1px solid var(--code-hl-bg-color)}div[class*=language-].ext-c:before{content:"c"}div[class*=language-].ext-cpp:before{content:"cpp"}div[class*=language-].ext-cs:before{content:"cs"}div[class*=language-].ext-css:before{content:"css"}div[class*=language-].ext-dart:before{content:"dart"}div[class*=language-].ext-docker:before{content:"docker"}div[class*=language-].ext-fs:before{content:"fs"}div[class*=language-].ext-go:before{content:"go"}div[class*=language-].ext-html:before{content:"html"}div[class*=language-].ext-java:before{content:"java"}div[class*=language-].ext-js:before{content:"js"}div[class*=language-].ext-json:before{content:"json"}div[class*=language-].ext-kt:before{content:"kt"}div[class*=language-].ext-less:before{content:"less"}div[class*=language-].ext-makefile:before{content:"makefile"}div[class*=language-].ext-md:before{content:"md"}div[class*=language-].ext-php:before{content:"php"}div[class*=language-].ext-py:before{content:"py"}div[class*=language-].ext-rb:before{content:"rb"}div[class*=language-].ext-rs:before{content:"rs"}div[class*=language-].ext-sass:before{content:"sass"}div[class*=language-].ext-scss:before{content:"scss"}div[class*=language-].ext-sh:before{content:"sh"}div[class*=language-].ext-styl:before{content:"styl"}div[class*=language-].ext-ts:before{content:"ts"}div[class*=language-].ext-toml:before{content:"toml"}div[class*=language-].ext-vue:before{content:"vue"}div[class*=language-].ext-yml:before{content:"yml"}@media (max-width:419px){.theme-default-content div[class*=language-]{margin:.85rem -1.5rem;border-radius:0}}.code-group__nav{margin-top:.85rem;margin-bottom:calc(-1.7rem - 6px);padding-bottom:calc(1.7rem - 6px);padding-left:10px;padding-top:10px;border-top-left-radius:6px;border-top-right-radius:6px;background-color:var(--code-bg-color)}.code-group__ul{margin:auto 0;padding-left:0;display:inline-flex;list-style:none}.code-group__nav-tab{border:0;padding:5px;cursor:pointer;background-color:transparent;font-size:.85em;line-height:1.4;color:#ffffffe6;font-weight:600}.code-group__nav-tab:focus{outline:0}.code-group__nav-tab:focus-visible{outline:1px solid rgba(255,255,255,.9)}.code-group__nav-tab-active{border-bottom:var(--c-brand) 1px solid}@media (max-width:419px){.code-group__nav{margin-left:-1.5rem;margin-right:-1.5rem;border-radius:0}}.code-group-item,.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subtitle>a.router-link-active:after{display:none}.code-group-item__active{display:block}.code-group-item>pre{background-color:orange}.custom-container{transition:color var(--t-color),border-color var(--t-color),background-color var(--t-color)}.custom-container .custom-container-title{font-weight:600;margin-bottom:-.4rem}.custom-container.danger,.custom-container.tip,.custom-container.warning{padding:.1rem 1.5rem;border-left-width:.5rem;border-left-style:solid;margin:1rem 0}.custom-container.tip{border-color:var(--c-tip);background-color:var(--c-tip-bg);color:var(--c-tip-text)}.custom-container.tip .custom-container-title{color:var(--c-tip-title)}.custom-container.tip a{color:var(--c-tip-text-accent)}.custom-container.warning{border-color:var(--c-warning);background-color:var(--c-warning-bg);color:var(--c-warning-text)}.custom-container.warning .custom-container-title{color:var(--c-warning-title)}.custom-container.warning a{color:var(--c-warning-text-accent)}.custom-container.danger{border-color:var(--c-danger);background-color:var(--c-danger-bg);color:var(--c-danger-text)}.custom-container.danger .custom-container-title{color:var(--c-danger-title)}.custom-container.danger a{color:var(--c-danger-text-accent)}.custom-container.details{display:block;position:relative;border-radius:2px;margin:1.6em 0;padding:1.6em;background-color:var(--c-details-bg)}.custom-container.details h4{margin-top:0}.custom-container.details figure:last-child,.custom-container.details p:last-child{margin-bottom:0;padding-bottom:0}.custom-container.details summary{outline:0;cursor:pointer}.home{padding:var(--navbar-height) 2rem 0;max-width:var(--homepage-width);margin:0 auto;display:block}.home .hero{text-align:center}.home .hero img{max-width:100%;max-height:280px;display:block;margin:3rem auto 1.5rem}.home .hero h1{font-size:3rem}.home .hero .actions,.home .hero .description,.home .hero h1{margin:1.8rem auto}.home .hero .actions{display:flex;flex-wrap:wrap;gap:1rem;justify-content:center}.home .hero .description{max-width:35rem;font-size:1.6rem;line-height:1.3;color:var(--c-text-lightest)}.home .hero .action-button{display:inline-block;font-size:1.2rem;padding:.8rem 1.6rem;border-width:2px;border-style:solid;border-radius:4px;transition:background-color var(--t-color);box-sizing:border-box}.home .hero .action-button.primary{color:var(--c-bg);background-color:var(--c-brand);border-color:var(--c-brand)}.home .hero .action-button.primary:hover{background-color:var(--c-brand-light)}.home .hero .action-button.secondary{color:var(--c-brand);background-color:var(--c-bg);border-color:var(--c-brand)}.home .hero .action-button.secondary:hover{color:var(--c-bg);background-color:var(--c-brand-light)}.home .features{border-top:1px solid var(--c-border);transition:border-color var(--t-color);padding:1.2rem 0;margin-top:2.5rem;display:flex;flex-wrap:wrap;align-items:flex-start;align-content:stretch;justify-content:space-between}.home .feature{flex-grow:1;flex-basis:30%;max-width:30%}.home .feature h2{font-size:1.4rem;font-weight:500;border-bottom:none;padding-bottom:0;color:var(--c-text-light)}.home .feature p,.home .footer{color:var(--c-text-lighter)}.home .footer{padding:2.5rem;border-top:1px solid var(--c-border);text-align:center;transition:border-color var(--t-color)}@media (max-width:719px){.home .features{flex-direction:column}.home .feature{max-width:100%;padding:0 2.5rem}}@media (max-width:419px){.home{padding-left:1.5rem;padding-right:1.5rem}.home .hero img{max-height:210px;margin:2rem auto 1.2rem}.home .hero h1{font-size:2rem}.home .hero .actions,.home .hero .description,.home .hero h1{margin:1.2rem auto}.home .hero .description{font-size:1.2rem}.home .hero .action-button{font-size:1rem;padding:.6rem 1.2rem}.home .feature h2{font-size:1.25rem}}.page{padding-top:var(--navbar-height);padding-left:var(--sidebar-width)}.navbar,.sidebar{position:fixed;left:0;box-sizing:border-box}.navbar{z-index:20;top:0;right:0;height:var(--navbar-height);border-bottom:1px solid var(--c-border);background-color:var(--c-bg-navbar);transition:background-color var(--t-color),border-color var(--t-color)}.sidebar{font-size:16px;width:var(--sidebar-width);z-index:10;margin:0;top:var(--navbar-height);bottom:0;border-right:1px solid var(--c-border);overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--c-brand) var(--c-border);background-color:var(--c-bg-sidebar);transition:transform var(--t-transform),background-color var(--t-color),border-color var(--t-color)}.sidebar::-webkit-scrollbar{width:7px}.sidebar::-webkit-scrollbar-track{background-color:var(--c-border)}.sidebar::-webkit-scrollbar-thumb{background-color:var(--c-brand)}.sidebar-mask{position:fixed;z-index:9;top:0;left:0;width:100vw;height:100vh;display:none}.theme-container.sidebar-open .sidebar-mask{display:block}.theme-container.sidebar-open .navbar>.toggle-sidebar-button .icon span:nth-child(1){transform:rotate(45deg) translate(5.5px,5.5px)}.theme-container.sidebar-open .navbar>.toggle-sidebar-button .icon span:nth-child(2){transform:scaleX(0)}.theme-container.sidebar-open .navbar>.toggle-sidebar-button .icon span:nth-child(3){transform:rotate(-45deg) translate(6px,-6px)}.theme-container.sidebar-open .navbar>.toggle-sidebar-button .icon span:nth-child(1),.theme-container.sidebar-open .navbar>.toggle-sidebar-button .icon span:nth-child(3){transform-origin:center}.theme-container.no-navbar .theme-default-content:not(.custom)>h1,.theme-container.no-navbar h2,.theme-container.no-navbar h3,.theme-container.no-navbar h4,.theme-container.no-navbar h5,.theme-container.no-navbar h6{margin-top:1.5rem;padding-top:0}.theme-container.no-navbar .page{padding-top:0}.theme-container.no-navbar .sidebar{top:0}@media (min-width:720px){.theme-container.no-sidebar .sidebar{display:none}.theme-container.no-sidebar .page{padding-left:0}}.theme-default-content:not(.custom)>h1,.theme-default-content:not(.custom)>h2,.theme-default-content:not(.custom)>h3,.theme-default-content:not(.custom)>h4,.theme-default-content:not(.custom)>h5,.theme-default-content:not(.custom)>h6{margin-top:calc(.5rem - var(--navbar-height));padding-top:calc(1rem + var(--navbar-height));margin-bottom:0}.theme-default-content:not(.custom)>h1:first-child,.theme-default-content:not(.custom)>h2:first-child,.theme-default-content:not(.custom)>h3:first-child,.theme-default-content:not(.custom)>h4:first-child,.theme-default-content:not(.custom)>h5:first-child,.theme-default-content:not(.custom)>h6:first-child{margin-bottom:1rem}.theme-default-content:not(.custom)>h1:first-child+.custom-container,.theme-default-content:not(.custom)>h1:first-child+p,.theme-default-content:not(.custom)>h1:first-child+pre,.theme-default-content:not(.custom)>h2:first-child+.custom-container,.theme-default-content:not(.custom)>h2:first-child+p,.theme-default-content:not(.custom)>h2:first-child+pre,.theme-default-content:not(.custom)>h3:first-child+.custom-container,.theme-default-content:not(.custom)>h3:first-child+p,.theme-default-content:not(.custom)>h3:first-child+pre,.theme-default-content:not(.custom)>h4:first-child+.custom-container,.theme-default-content:not(.custom)>h4:first-child+p,.theme-default-content:not(.custom)>h4:first-child+pre,.theme-default-content:not(.custom)>h5:first-child+.custom-container,.theme-default-content:not(.custom)>h5:first-child+p,.theme-default-content:not(.custom)>h5:first-child+pre,.theme-default-content:not(.custom)>h6:first-child+.custom-container,.theme-default-content:not(.custom)>h6:first-child+p,.theme-default-content:not(.custom)>h6:first-child+pre{margin-top:2rem}.theme-default-content:not(.custom){max-width:var(--content-width);margin:0 auto;padding:2rem 2.5rem;padding-top:0}@media (max-width:959px){.theme-default-content:not(.custom){padding:2rem}}@media (max-width:419px){.theme-default-content:not(.custom){padding:1.5rem}}.theme-default-content:not(.custom) a:hover{text-decoration:underline}.theme-default-content:not(.custom) img{max-width:100%}.theme-default-content.custom{padding:0;margin:0}.theme-default-content.custom img{max-width:100%}@media (max-width:959px){.sidebar{font-size:15px;width:var(--sidebar-width-mobile)}.page{padding-left:var(--sidebar-width-mobile)}}@media (max-width:719px){.sidebar{top:0;padding-top:var(--navbar-height);transform:translate(-100%)}.page{padding-left:0}.theme-container.sidebar-open .sidebar{transform:translate(0)}.theme-container.no-navbar .sidebar{padding-top:0}}@media (max-width:419px){h1{font-size:1.9rem}}.navbar{--navbar-line-height:calc( var(--navbar-height) - 2 * var(--navbar-padding-v) );padding:var(--navbar-padding-v) var(--navbar-padding-h);line-height:var(--navbar-line-height)}.navbar .logo{height:var(--navbar-line-height);margin-right:var(--navbar-padding-v);vertical-align:top}.navbar .site-name{font-size:1.3rem;font-weight:600;color:var(--c-text);position:relative}.navbar .navbar-items-wrapper{display:flex;position:absolute;box-sizing:border-box;top:var(--navbar-padding-v);right:var(--navbar-padding-h);height:var(--navbar-line-height);padding-left:var(--navbar-padding-h);white-space:nowrap;font-size:.9rem}.navbar .navbar-items-wrapper .search-box{flex:0 0 auto;vertical-align:top}@media (max-width:719px){.navbar{padding-left:4rem}.navbar .can-hide{display:none}.navbar .site-name{width:calc(100vw - 9.4rem);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}}.navbar-items,.navbar-items a{display:inline-block}.navbar-items a{line-height:1.4rem;color:inherit}.navbar-items a.router-link-active,.navbar-items a:hover{color:var(--c-text-accent)}.navbar-items .navbar-item{position:relative;display:inline-block;margin-left:1.5rem;line-height:var(--navbar-line-height)}.navbar-items .navbar-item:first-child{margin-left:0}@media (max-width:719px){.navbar-items .navbar-item{margin-left:0}}@media (min-width:719px){.navbar-items a.router-link-active,.navbar-items a:hover{color:var(--c-text)}.navbar-item>a.router-link-active,.navbar-item>a:hover{margin-bottom:-2px;border-bottom:2px solid var(--c-text-accent)}}.toggle-sidebar-button{position:absolute;top:.6rem;left:1rem;display:none;padding:.6rem;cursor:pointer}.toggle-sidebar-button .icon{display:flex;flex-direction:column;justify-content:center;align-items:center;width:1.25rem;height:1.25rem;cursor:inherit}.toggle-sidebar-button .icon span{display:inline-block;width:100%;height:2px;border-radius:2px;background-color:var(--c-text);transition:transform var(--t-transform)}.toggle-sidebar-button .icon span:nth-child(2){margin:6px 0}@media screen and (max-width:719px){.toggle-sidebar-button{display:block}}.toggle-dark-button{display:flex;margin:auto;margin-left:1rem;border:0;background:0 0;color:var(--c-text);opacity:.8;cursor:pointer}.toggle-dark-button:hover{opacity:1}.toggle-dark-button .icon{width:1.25rem;height:1.25rem}.navbar-dropdown-wrapper{cursor:pointer}.navbar-dropdown-wrapper .navbar-dropdown-title,.navbar-dropdown-wrapper .navbar-dropdown-title-mobile{display:block;font-size:.9rem;font-family:inherit;cursor:inherit;padding:inherit;line-height:1.4rem;background:0 0;border:0;font-weight:500;color:var(--c-text)}.navbar-dropdown-wrapper .navbar-dropdown-title-mobile{display:none;font-weight:600;font-size:inherit}.navbar-dropdown-wrapper .navbar-dropdown-title-mobile:hover,.navbar-dropdown-wrapper .navbar-dropdown-title:hover{border-color:transparent}.navbar-dropdown-wrapper .navbar-dropdown-title .arrow,.navbar-dropdown-wrapper .navbar-dropdown-title-mobile .arrow{vertical-align:middle;margin-top:-1px;margin-left:.4rem}.navbar-dropdown-wrapper .navbar-dropdown-title-mobile:hover{color:var(--c-text-accent)}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item{color:inherit;line-height:1.7rem}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subtitle{margin:.45rem 0 0;border-top:1px solid var(--c-border);padding:1rem 0 .45rem;font-size:.9rem}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subtitle>span{padding:0 1.5rem 0 1.25rem}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subtitle>a{font-weight:inherit}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subitem-wrapper{padding:0;list-style:none}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subitem-wrapper .navbar-dropdown-subitem{font-size:.9em}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item a{display:block;line-height:1.7rem;position:relative;border-bottom:none;font-weight:400;margin-bottom:0;padding:0 1.5rem 0 1.25rem}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item a.router-link-active,.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item a:hover{color:var(--c-text-accent)}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item a.router-link-active:after{content:"";width:0;height:0;border-left:5px solid var(--c-text-accent);border-top:3px solid transparent;border-bottom:3px solid transparent;position:absolute;top:calc(50% - 2px);left:9px}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item:first-child .navbar-dropdown-subtitle{margin-top:0;padding-top:0;border-top:0}@media (max-width:719px){.navbar-dropdown-wrapper.open .navbar-dropdown-title,.navbar-dropdown-wrapper.open .navbar-dropdown-title-mobile{margin-bottom:.5rem}.navbar-dropdown-wrapper .navbar-dropdown-title{display:none}.navbar-dropdown-wrapper .navbar-dropdown-title-mobile{display:block}.navbar-dropdown-wrapper .navbar-dropdown{transition:height .1s ease-out;overflow:hidden}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subtitle{border-top:0;margin-top:0;padding-top:0;padding-bottom:0;font-size:15px;line-height:2rem}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item>a{font-size:15px;line-height:2rem}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subitem{font-size:14px;padding-left:1rem}}@media (min-width:720px){.navbar-dropdown-wrapper{height:1.8rem}.navbar-dropdown-wrapper.open .navbar-dropdown,.navbar-dropdown-wrapper:hover .navbar-dropdown{display:block!important}.navbar-dropdown-wrapper.open:blur{display:none}.navbar-dropdown-wrapper .navbar-dropdown{display:none;height:auto!important;box-sizing:border-box;max-height:calc(100vh - 2.7rem);overflow-y:auto;position:absolute;top:100%;right:0;background-color:var(--c-bg-navbar);padding:.6rem 0;border:1px solid var(--c-border);border-bottom-color:var(--c-border-dark);text-align:left;border-radius:.25rem;white-space:nowrap;margin:0}}.page{padding-bottom:2rem;display:block}.page-meta{max-width:var(--content-width);margin:0 auto;padding:1rem 2.5rem;overflow:auto}@media (max-width:959px){.page-meta{padding:2rem}}@media (max-width:419px){.page-meta{padding:1.5rem}}.page-meta .meta-item{cursor:default;margin-top:.8rem}.page-meta .meta-item .meta-item-label{font-weight:500;color:var(--c-text-lighter)}.page-meta .meta-item .meta-item-info{font-weight:400;color:var(--c-text-quote)}.page-meta .edit-link{display:inline-block;margin-right:.25rem}.page-meta .last-updated{float:right}@media (max-width:719px){.page-meta .last-updated{font-size:.8em;float:none}.page-meta .contributors{font-size:.8em}}.page-nav{max-width:var(--content-width);margin:0 auto;padding:1rem 2.5rem 2rem;padding-bottom:0}@media (max-width:959px){.page-nav{padding:2rem}}@media (max-width:419px){.page-nav{padding:1.5rem}}.page-nav .inner{min-height:2rem;margin-top:0;border-top:1px solid var(--c-border);transition:border-color var(--t-color);padding-top:1rem;overflow:auto}.page-nav .prev a:before{content:"\2190"}.page-nav .next{float:right}.page-nav .next a:after{content:"\2192"}.sidebar ul{padding:0;margin:0;list-style-type:none}.sidebar a{display:inline-block}.sidebar .navbar-items{display:none;border-bottom:1px solid var(--c-border);transition:border-color var(--t-color);padding:.5rem 0 .75rem}.sidebar .navbar-items a{font-weight:600}.sidebar .navbar-items .navbar-item{display:block;line-height:1.25rem;font-size:1.1em;padding:.5rem 0 .5rem 1.5rem}.sidebar .sidebar-items{padding:1.5rem 0}@media (max-width:719px){.sidebar .navbar-items{display:block}.sidebar .navbar-items .navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item a.router-link-active:after{top:calc(1rem - 2px)}.sidebar .sidebar-items{padding:1rem 0}}.sidebar-item{cursor:default}.sidebar-item.sidebar-heading{color:var(--c-text);transition:color .15s ease;font-size:1.1em;font-weight:700;padding:.35rem 1.5rem .35rem 1.25rem;width:100%;box-sizing:border-box;margin:0;border-left:.25rem solid transparent}.sidebar-item.sidebar-heading.collapsible,a.sidebar-item{cursor:pointer}.sidebar-item.sidebar-heading.collapsible+.sidebar-item-children{transition:height .1s ease-out;overflow:hidden;margin-bottom:.75rem}.sidebar-item.sidebar-heading .arrow{position:relative;top:-.12em;left:.5em}.sidebar-item:not(.sidebar-heading){font-size:1em;font-weight:400;display:inline-block;color:var(--c-text);border-left:.25rem solid transparent;margin:0;padding:.35rem 1rem .35rem 2rem;line-height:1.4;width:100%;box-sizing:border-box}.sidebar-item:not(.sidebar-heading).active{font-weight:600;color:var(--c-text-accent);border-left-color:var(--c-text-accent)}.sidebar-item:not(.sidebar-heading)+.sidebar-item-children{padding-left:1rem;font-size:.95em}.sidebar-item-children .sidebar-item-children .sidebar-item:not(.sidebar-heading){padding:.25rem 1rem .25rem 1.75rem}.sidebar-item-children .sidebar-item-children .sidebar-item:not(.sidebar-heading).active{font-weight:500;border-left-color:transparent}a.sidebar-item:hover{color:var(--c-text-accent)}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.table-of-contents .badge{vertical-align:middle}.dropdown-enter-from,.dropdown-leave-to{height:0!important}.fade-slide-y-enter-active{transition:all .3s ease}.fade-slide-y-leave-active{transition:all .3s cubic-bezier(1,.5,.8,1)}.fade-slide-y-enter-from,.fade-slide-y-leave-to{transform:translateY(10px);opacity:0}:root{scroll-behavior:smooth}:root{--search-bg-color:#ffffff;--search-accent-color:#3eaf7c;--search-text-color:#2c3e50;--search-border-color:#eaecef;--search-item-text-color:#5d81a5;--search-item-focus-bg-color:#f3f4f5;--search-input-width:8rem;--search-result-width:20rem}.search-box{display:inline-block;position:relative;margin-left:1rem}.search-box input{cursor:text;width:var(--search-input-width);height:2rem;color:var(--search-text-color);display:inline-block;border:1px solid var(--search-border-color);border-radius:2rem;font-size:.9rem;line-height:2rem;padding:0 .5rem 0 2rem;outline:0;transition:all ease .3s;background:var(--search-bg-color) url(/Husky.Net/assets/search.0782d0d1.svg) .6rem .5rem no-repeat;background-size:1rem}.search-box input:focus{cursor:auto;border-color:var(--search-accent-color)}.search-box .suggestions{background:var(--search-bg-color);width:var(--search-result-width);position:absolute;top:2rem;right:0;border:1px solid var(--search-border-color);border-radius:6px;padding:.4rem;list-style-type:none}.search-box .suggestion{line-height:1.4;padding:.4rem .6rem;border-radius:4px;cursor:pointer}.search-box .suggestion.focus{background-color:var(--search-item-focus-bg-color)}.search-box .suggestion.focus a{color:var(--search-accent-color)}.search-box .suggestion a{white-space:normal;color:var(--search-item-text-color)}.search-box .suggestion .page-title{font-weight:600}.search-box .suggestion .page-header{font-size:.9em;margin-left:.25em}@media (max-width:720px){.search-box input{cursor:pointer;width:0;border-color:transparent;position:relative}.search-box input:focus{cursor:text;left:0;width:10rem}}@media (max-width:420px){.search-box input:focus{width:8rem}.search-box .suggestions{width:calc(100vw - 4rem);right:-.5rem}}:root{--back-to-top-z-index:5;--back-to-top-color:#3eaf7c;--back-to-top-color-hover:#71cda3}.back-to-top{cursor:pointer;position:fixed;bottom:2rem;right:2.5rem;width:2rem;height:1.2rem;background-color:var(--back-to-top-color);-webkit-mask:url(/Husky.Net/assets/back-to-top.8efcbe56.svg) no-repeat;mask:url(/Husky.Net/assets/back-to-top.8efcbe56.svg) no-repeat;z-index:var(--back-to-top-z-index)}.back-to-top:hover{background-color:var(--back-to-top-color-hover)}@media (max-width:959px){.back-to-top{display:none}}.back-to-top-enter-active,.back-to-top-leave-active{transition:opacity .3s}.back-to-top-enter-from,.back-to-top-leave-to{opacity:0}:root{--nprogress-color:#29d;--nprogress-z-index:1031}#nprogress{pointer-events:none}#nprogress .bar{background:var(--nprogress-color);position:fixed;z-index:var(--nprogress-z-index);top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px var(--nprogress-color),0 0 5px var(--nprogress-color);opacity:1;transform:rotate(3deg) translateY(-4px)}
diff --git a/assets/submodules.html.2b2978a2.js b/assets/submodules.html.2b2978a2.js
new file mode 100644
index 0000000..9158b36
--- /dev/null
+++ b/assets/submodules.html.2b2978a2.js
@@ -0,0 +1,8 @@
+import{r as u,o as l,c as p,b as a,a as s,w as e,F as c,e as t,d as o}from"./app.22727b9e.js";import{_ as i}from"./plugin-vue_export-helper.21dcd24c.js";const d={},r=a("h1",{id:"git-submodules",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#git-submodules","aria-hidden":"true"},"#"),t(" Git submodules")],-1),h=a("p",null,"Husky handles git submodules in two ways:",-1),k=a("li",null,"The project hooks and husky steps are completely ignored when the project is a git submodule.",-1),g=t("The hooks are installed in the submodule's git directory. This is the default mode following the step in "),m=t("Installation"),_=t(" and "),y=t("Attach Husky to your project"),b=t(" should get you up and running."),q=o(`
For Husky to ignore installing when in a submodule, call dotnet husky install --ignore-submodule. This will make the install step a no-op. No git configurations will be applied and your hooks won't be attached.
A message will alert you when this is happening:
Submodule detected and [--ignore-when-submodule] is set, skipping install target
+
`,9),v=t("The "),f=a("code",null,"attach",-1),w=t(" command offers a "),x=a("code",null,"--ignore-submodule",-1),I=t(" options that generates an MsBuild target you can skip by setting the "),S=a("code",null,"IgnoreSubmodule",-1),T=t(" variable to "),j=a("code",null,"0",-1),C=t(" similar to the "),H=a("code",null,"Husky",-1),N=t(" variable, see "),R=t("Disable husky in CI/CD pipelines"),B=o(`
The generated block will look something like this, If you're attaching husky manually copy the target to your .csproj and adjust WorkingDirectory accordingly.
<TargetName="husky"BeforeTargets="Restore;CollectPackageReferences"Condition="'$(HUSKY)' != 0 and '$(IgnoreSubmodule)' != 0">
+ <ExecCommand="dotnet tool restore"StandardOutputImportance="Low"StandardErrorImportance="High"/>
+ <ExecCommand="dotnet husky install --ignore-submodule"StandardOutputImportance="Low"StandardErrorImportance="High"
+ WorkingDirectory="../../"/><!--Update this to the relative path to your project root dir -->
+</Target>
+
TIP
If you want your submodule hooks ignored but still want the MsBuild target to run, remove the and '$(IgnoreSubmodule)' != 0 condition. dotnet husky install --ignore-submodule is enough to prevent the installation of the hooks.
`,3);function E(A,D){const n=u("RouterLink");return l(),p(c,null,[r,h,a("ul",null,[k,a("li",null,[g,s(n,{to:"/guide/getting-started.md/#installation"},{default:e(()=>[m]),_:1}),_,s(n,{to:"/guide/automate.md/#attach-husky-to-your-project"},{default:e(()=>[y]),_:1}),b])]),q,a("p",null,[v,f,w,x,I,S,T,j,C,H,N,s(n,{to:"/guide/automate.html#disable-husky-in-ci-cd-pipelines"},{default:e(()=>[R]),_:1})]),B],64)}var V=i(d,[["render",E]]);export{V as default};
diff --git a/assets/submodules.html.7c452965.js b/assets/submodules.html.7c452965.js
new file mode 100644
index 0000000..771fda0
--- /dev/null
+++ b/assets/submodules.html.7c452965.js
@@ -0,0 +1 @@
+const e={key:"v-7b646586",path:"/guide/submodules.html",title:"Git submodules",lang:"en-US",frontmatter:{},excerpt:"",headers:[{level:2,title:"Installing husky",slug:"installing-husky",children:[{level:3,title:"Ignoring submodule install",slug:"ignoring-submodule-install",children:[]}]},{level:2,title:"Attaching husky",slug:"attaching-husky",children:[]}],git:{updatedTime:1693060964e3},filePathRelative:"guide/submodules.md"};export{e as data};
diff --git a/assets/task-configuration.html.9ea86763.js b/assets/task-configuration.html.9ea86763.js
new file mode 100644
index 0000000..ec36e6b
--- /dev/null
+++ b/assets/task-configuration.html.9ea86763.js
@@ -0,0 +1,17 @@
+import{r as n,o as a,c as r,b as t,a as o,F as d,d as e,e as l}from"./app.22727b9e.js";import{_ as i}from"./plugin-vue_export-helper.21dcd24c.js";const c={},p=e('
Husky.Net supports the standard dotnet FileSystemGlobbing patterns for include or exclude task configurations. The patterns that are specified in the include and exclude can use the following formats to match multiple files or directories.
Exact directory or file name
some-file.txt
path/to/file.txt
Wildcards * in file and directory names that represent zero to many characters not including separator characters.
Value
Description
*.txt
All files with .txt file extension.
.
All files with an extension.
*
All files in top-level directory.
.*
File names beginning with '.'.
word
All files with 'word' in the filename.
readme.*
All files named 'readme' with any file extension.
styles/*.css
All files with extension '.css' in the directory 'styles/'.
scripts//
All files in 'scripts/' or one level of subdirectory under 'scripts/'.
images*/*
All files in a folder with name that is or begins with 'images'.
Arbitrary directory depth (/**/).
Value
Description
*/
All files in any subdirectory.
dir/**/*
All files in any subdirectory under 'dir/'.
Relative paths.
To match all files in a directory named "shared" at the sibling level to the base directory use ../shared/*.
',11),u={href:"https://docs.microsoft.com/en-us/dotnet/core/extensions/file-globbing#pattern-formats",target:"_blank",rel:"noopener noreferrer"},h=l("Read more here"),b=e(`
There are some variables that you can use in your task arguments (args).
\${staged}
returns the list of currently staged files
\${last-commit}
returns last commit changed files
\${git-files}
returns the output of (git ls-files)
\${all-files}
returns the list of matched files using include/exclude, be careful with this variable, it will return all the files if you don't specify include or exclude
\${args}
returns the arguments passed directly to the husky run command using --args option
Linting makes more sense when run before committing your code. By doing so you can ensure no errors go into the repository and enforce code style. But running a lint process on a whole project is slow, and linting results can be irrelevant. Ultimately you only want to lint files that will be committed.
`,9);function p(o,e){return t}var r=s(a,[["render",p]]);export{r as default};
diff --git a/assets/troubleshoot.html.42443789.js b/assets/troubleshoot.html.42443789.js
new file mode 100644
index 0000000..3c1a53b
--- /dev/null
+++ b/assets/troubleshoot.html.42443789.js
@@ -0,0 +1 @@
+import{r as s,o as i,c as r,b as e,a as n,F as a,e as t,d as l}from"./app.22727b9e.js";import{_ as d}from"./plugin-vue_export-helper.21dcd24c.js";var c="/Husky.Net/assets/without_emojis.375b51ee.png",h="/Husky.Net/assets/with_emojis.4821a031.png";const u={},_=e("h1",{id:"missing-emojis",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#missing-emojis","aria-hidden":"true"},"#"),t(" Missing Emojis")],-1),m=e("p",null,[t("If emojies are missing when you use "),e("code",null,"Husky.Net"),t(" under Windows environment you can check these points below :")],-1),p=t("You have the latest version of "),g={href:"https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701#activetab=pivot:overviewtab",target:"_blank",rel:"noopener noreferrer"},f=t("Windows Terminal"),b=t("The font used by the terminal is a "),w={href:"https://github.com/powerline/fonts",target:"_blank",rel:"noopener noreferrer"},v=t("powerline"),k=t(" or a "),y={href:"https://www.nerdfonts.com/",target:"_blank",rel:"noopener noreferrer"},j=t("nerd fonts"),x=e("li",null,[t("You have enable the new UTF-8 option in Windows settings "),e("ol",null,[e("li",null,[t("Go to the "),e("a",{href:"ms-settings:regionlanguage"},"Language Settings")]),e("li",null,[t("Administrative language settings > Change system locale > Check "),e("code",null,"Beta: Use Unicode UTF-8 for worldwide language support")]),e("li",null,"Restart your computer")])],-1),N=l('
If none of the above solutions worked, you can disable husky unicode characters by setting the HUSKY_NOUNICODE environment variable to true or use the no-unicode or -u option after husky run command.
',3);function E(U,B){const o=s("ExternalLinkIcon");return i(),r(a,null,[_,m,e("ul",null,[e("li",null,[p,e("a",g,[f,n(o)])]),e("li",null,[b,e("a",w,[v,n(o)]),k,e("a",y,[j,n(o)])]),x]),N],64)}var W=d(u,[["render",E]]);export{W as default};
diff --git a/assets/troubleshoot.html.5431d5aa.js b/assets/troubleshoot.html.5431d5aa.js
new file mode 100644
index 0000000..127e558
--- /dev/null
+++ b/assets/troubleshoot.html.5431d5aa.js
@@ -0,0 +1 @@
+const e={key:"v-c83fcc36",path:"/guide/troubleshoot.html",title:"Missing Emojis",lang:"en-US",frontmatter:{},excerpt:"",headers:[{level:2,title:"Disabling Emojis",slug:"disabling-emojis",children:[]}],git:{updatedTime:1659123368e3},filePathRelative:"guide/troubleshoot.md"};export{e as data};
diff --git a/assets/with_emojis.4821a031.png b/assets/with_emojis.4821a031.png
new file mode 100644
index 0000000..302e07c
Binary files /dev/null and b/assets/with_emojis.4821a031.png differ
diff --git a/assets/without_emojis.375b51ee.png b/assets/without_emojis.375b51ee.png
new file mode 100644
index 0000000..74320bf
Binary files /dev/null and b/assets/without_emojis.375b51ee.png differ
diff --git a/assets/workflow.290a20c9.jpg b/assets/workflow.290a20c9.jpg
new file mode 100644
index 0000000..0097d14
Binary files /dev/null and b/assets/workflow.290a20c9.jpg differ
diff --git a/contribution/index.html b/contribution/index.html
new file mode 100644
index 0000000..c610b0e
--- /dev/null
+++ b/contribution/index.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+ Contribute to the project | Husky.Net
+
+
+
+
+
Husky.Net brings the dev-dependency concept to the .NET ecosystem.
You can attach husky to your project without adding extra dependencies! This way the other contributors will use your pre-configured tasks automatically.
To manually attach husky to your project, add the below code to one of your projects (.csproj/.vbproj).
<TargetName="husky"BeforeTargets="Restore;CollectPackageReferences"Condition="'$(HUSKY)' != 0">
+ <ExecCommand="dotnet tool restore"StandardOutputImportance="Low"StandardErrorImportance="High"/>
+ <ExecCommand="dotnet husky install"StandardOutputImportance="Low"StandardErrorImportance="High"
+ WorkingDirectory="../../"/><!--Update this to the relative path to your project root dir -->
+</Target>
+
TIP
Make sure to update the working directory depending on your folder structure it should be a relative path to your project root dir
WARNING
Adding the above code to a multiple targeted project will cause husky to run multiple times. e.g <TargetFrameworks>netcoreapp3.1;net5.0;net6.0;net7.0</TargetFrameworks>
to avoid this, you can add the $(IsCrossTargetingBuild)' == 'true' condition to the target. e.g
<TargetName="husky"BeforeTargets="Restore;CollectPackageReferences"Condition="'$(HUSKY)' != 0 and '$(IsCrossTargetingBuild)' == 'true'">
+...
+
Run linters against staged git files and don't let 💩 slip into your code base!
These two quotes from huskyopen in new window and lint-stagedopen in new window JS tools inspired me to create Husky.Net for dotnet developers. it provides a simple native way to do both also has a lot of other cool features, You can use it to lint your commit messages, run tests, lint/format code, etc... when you commit or push. 🚀🚀
We, as developers, love platforms like GitHub, GitLab, Atlassian, Azure DevOps etc., as our managed git system and collaboration platform. We also love clean code and keep inventing new linters and rules to enforce it. In my opinion, every commit should allow the codebase to deploy to production. There is nothing worse than commits like “fixed style errors” or “fixed build”. These are often small mistakes you want to know as early as possible in your development cycle. You don’t want to break the build for the next developer because he pulled your ‘mistake’ or waste precious build minutes of your CI server. Say you have asked your teammate to review your code; in the meantime, the build server rejects your code. That means you have to go back and fix this, and your teammate has to come back and possibly review again after the changes (i.e., approvals reset on new commit). Doing so would waste a lot of time and effort.
Husky.Net offers a very simple way to start using git hooks or running certain tasks, write and run custom scripts and more ...
The project hooks and husky steps are completely ignored when the project is a git submodule.
The hooks are installed in the submodule's git directory. This is the default mode following the step in Installation and Attach Husky to your project should get you up and running.
For Husky to ignore installing when in a submodule, call dotnet husky install --ignore-submodule. This will make the install step a no-op. No git configurations will be applied and your hooks won't be attached.
A message will alert you when this is happening:
Submodule detected and [--ignore-when-submodule] is set, skipping install target
+
The attach command offers a --ignore-submodule options that generates an MsBuild target you can skip by setting the IgnoreSubmodule variable to 0 similar to the Husky variable, see Disable husky in CI/CD pipelines
The generated block will look something like this, If you're attaching husky manually copy the target to your .csproj and adjust WorkingDirectory accordingly.
<TargetName="husky"BeforeTargets="Restore;CollectPackageReferences"Condition="'$(HUSKY)' != 0 and '$(IgnoreSubmodule)' != 0">
+ <ExecCommand="dotnet tool restore"StandardOutputImportance="Low"StandardErrorImportance="High"/>
+ <ExecCommand="dotnet husky install --ignore-submodule"StandardOutputImportance="Low"StandardErrorImportance="High"
+ WorkingDirectory="../../"/><!--Update this to the relative path to your project root dir -->
+</Target>
+
TIP
If you want your submodule hooks ignored but still want the MsBuild target to run, remove the and '$(IgnoreSubmodule)' != 0 condition. dotnet husky install --ignore-submodule is enough to prevent the installation of the hooks.
Husky.Net supports the standard dotnet FileSystemGlobbing patterns for include or exclude task configurations. The patterns that are specified in the include and exclude can use the following formats to match multiple files or directories.
Exact directory or file name
some-file.txt
path/to/file.txt
Wildcards * in file and directory names that represent zero to many characters not including separator characters.
Value
Description
*.txt
All files with .txt file extension.
.
All files with an extension.
*
All files in top-level directory.
.*
File names beginning with '.'.
word
All files with 'word' in the filename.
readme.*
All files named 'readme' with any file extension.
styles/*.css
All files with extension '.css' in the directory 'styles/'.
scripts//
All files in 'scripts/' or one level of subdirectory under 'scripts/'.
images*/*
All files in a folder with name that is or begins with 'images'.
Arbitrary directory depth (/**/).
Value
Description
*/
All files in any subdirectory.
dir/**/*
All files in any subdirectory under 'dir/'.
Relative paths.
To match all files in a directory named "shared" at the sibling level to the base directory use ../shared/*.
There are some variables that you can use in your task arguments (args).
${staged}
returns the list of currently staged files
${last-commit}
returns last commit changed files
${git-files}
returns the output of (git ls-files)
${all-files}
returns the list of matched files using include/exclude, be careful with this variable, it will return all the files if you don't specify include or exclude
${args}
returns the arguments passed directly to the husky run command using --args option
Linting makes more sense when run before committing your code. By doing so you can ensure no errors go into the repository and enforce code style. But running a lint process on a whole project is slow, and linting results can be irrelevant. Ultimately you only want to lint files that will be committed.
If none of the above solutions worked, you can disable husky unicode characters by setting the HUSKY_NOUNICODE environment variable to true or use the no-unicode or -u option after husky run command.