diff --git a/README.md b/README.md index f844706..46ab622 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,11 @@ +

+ + + + --argh_ + +

+ # Nullean.Argh [![NuGet](https://img.shields.io/nuget/v/Nullean.Argh.svg)](https://www.nuget.org/packages/Nullean.Argh) diff --git a/build/scripts/CommandLine.fs b/build/scripts/CommandLine.fs index 57545bc..1392f51 100644 --- a/build/scripts/CommandLine.fs +++ b/build/scripts/CommandLine.fs @@ -16,6 +16,8 @@ type Arguments = | [] UpdateSchema | [] ValidateSchema + | [] Docs + | [] Release | [] CreateReleaseOnGithub @@ -40,6 +42,7 @@ with | UpdateSchema -> "Run the schema export tool and write schema/argh-cli-schema.json" | ValidateSchema -> "Fail if schema/argh-cli-schema.json is out of date" + | Docs -> "Build the documentation site and serve it locally" | PristineCheck | GeneratePackages diff --git a/build/scripts/Documentation.fs b/build/scripts/Documentation.fs new file mode 100644 index 0000000..40ec8a1 --- /dev/null +++ b/build/scripts/Documentation.fs @@ -0,0 +1,208 @@ +/// Builds the public documentation locally and serves it. +/// +/// The branded landing page (argh-landing.html) is a standalone document that replaces the +/// generated index.html after the docs-builder build — the only way to preview the real site +/// is to build, apply the override, and serve the output. +module Documentation + +open System +open System.IO +open System.IO.Compression +open System.Net +open System.Net.Http +open System.Text +open System.Threading.Tasks +open ProcNet + +let private exec binary args = Proc.Exec(binary, List.toArray args) |> ignore + +let private docsSource = "docs" +let private landingPage = Path.Combine(docsSource, "argh-landing.html") + +/// docs-builder always writes here. +let private htmlOutput = Path.Combine(".artifacts", "docs", "html") + +// ───────────────────────────── acquiring docs-builder ───────────────────────────── + +let private toolPath = + let exe = if OperatingSystem.IsWindows() then "docs-builder.exe" else "docs-builder" + Path.Combine(".artifacts", "tools", exe) + +let private archiveName () = + let arch = + match Runtime.InteropServices.RuntimeInformation.OSArchitecture with + | Runtime.InteropServices.Architecture.Arm64 -> "arm64" + | Runtime.InteropServices.Architecture.X64 -> "x64" + | other -> failwithf "docs-builder ships no binary for %O" other + if OperatingSystem.IsMacOS() then sprintf "docs-builder-mac-%s.zip" arch + elif OperatingSystem.IsLinux() then sprintf "docs-builder-linux-%s.zip" arch + elif OperatingSystem.IsWindows() then sprintf "docs-builder-win-%s.zip" arch + else failwith "unsupported operating system for docs-builder" + +let ensureTool () = + if File.Exists toolPath then toolPath + else + + let archive = archiveName () + let version = + match Environment.GetEnvironmentVariable "DOCS_BUILDER_VERSION" with + | null | "" -> "latest" + | v -> v + let url = + match version with + | "latest" -> sprintf "https://github.com/elastic/docs-builder/releases/latest/download/%s" archive + | v -> sprintf "https://github.com/elastic/docs-builder/releases/download/%s/%s" v archive + + printfn "docs-builder not cached, downloading %s" url + Directory.CreateDirectory(Path.GetDirectoryName toolPath) |> ignore + + let zip = Path.Combine(Path.GetTempPath(), archive) + use client = new HttpClient() + client.Timeout <- TimeSpan.FromMinutes 5.0 + do + use response = client.GetAsync(url).GetAwaiter().GetResult() + response.EnsureSuccessStatusCode() |> ignore + use file = File.Create zip + response.Content.CopyToAsync(file).GetAwaiter().GetResult() + + let name = Path.GetFileName toolPath + do + use zipFile = ZipFile.OpenRead zip + let entry = + zipFile.Entries + |> Seq.tryFind (fun e -> String.Equals(e.Name, name, StringComparison.OrdinalIgnoreCase)) + |> Option.defaultWith (fun () -> failwithf "%s did not contain %s" archive name) + entry.ExtractToFile(toolPath, true) + File.Delete zip + + if not (OperatingSystem.IsWindows()) then + File.SetUnixFileMode( + toolPath, + UnixFileMode.UserRead ||| UnixFileMode.UserWrite ||| UnixFileMode.UserExecute + ||| UnixFileMode.GroupRead ||| UnixFileMode.GroupExecute + ||| UnixFileMode.OtherRead ||| UnixFileMode.OtherExecute) + + printfn "docs-builder cached at %s" toolPath + toolPath + +// ───────────────────────────── build ───────────────────────────── + +/// Build docs and apply the landing page override. +/// argh.nullean.net serves from the domain root — no path prefix needed. +let build () = + let tool = ensureTool () + + exec tool ["build"; "--path"; docsSource] + + if not (Directory.Exists htmlOutput) then + failwithf "docs-builder reported success but %s does not exist" htmlOutput + + File.Copy(landingPage, Path.Combine(htmlOutput, "index.html"), true) + printfn "applied landing page override -> %s" (Path.Combine(htmlOutput, "index.html")) + +// ───────────────────────────── serve ───────────────────────────── + +let private contentType (path: string) = + match Path.GetExtension(path).ToLowerInvariant() with + | ".html" | ".htm" -> "text/html; charset=utf-8" + | ".css" -> "text/css; charset=utf-8" + | ".js" | ".mjs" -> "text/javascript; charset=utf-8" + | ".json" -> "application/json; charset=utf-8" + | ".svg" -> "image/svg+xml" + | ".woff2"-> "font/woff2" + | ".woff" -> "font/woff" + | ".ttf" -> "font/ttf" + | ".png" -> "image/png" + | ".jpg" | ".jpeg" -> "image/jpeg" + | ".gif" -> "image/gif" + | ".webp" -> "image/webp" + | ".ico" -> "image/x-icon" + | ".txt" -> "text/plain; charset=utf-8" + | ".xml" -> "application/xml; charset=utf-8" + | ".wasm" -> "application/wasm" + | _ -> "application/octet-stream" + +let private writeResponse (response: HttpListenerResponse) (path: string) = + response.ContentType <- contentType path + let bytes = File.ReadAllBytes path + response.OutputStream.Write(bytes, 0, bytes.Length) + +let private notFound (response: HttpListenerResponse) (raw: string) = + response.StatusCode <- 404 + response.ContentType <- "text/plain; charset=utf-8" + let body = Encoding.UTF8.GetBytes(sprintf "404 %s" raw) + response.OutputStream.Write(body, 0, body.Length) + +let private handle (root: string) (context: HttpListenerContext) = + let response = context.Response + try + try + let raw = Uri.UnescapeDataString context.Request.Url.AbsolutePath + let candidate = Path.GetFullPath(Path.Combine(root, raw.TrimStart('/'))) + + if not (candidate.StartsWith(root, StringComparison.Ordinal)) then + notFound response raw + elif raw = "/" || raw = "" then + let index = Path.Combine(root, "index.html") + if File.Exists index then writeResponse response index else notFound response raw + elif File.Exists candidate then + writeResponse response candidate + elif Directory.Exists candidate then + if not (raw.EndsWith "/") then response.Redirect(raw + "/") + else + let index = Path.Combine(candidate, "index.html") + if File.Exists index then writeResponse response index else notFound response raw + else + notFound response raw + with e -> + response.StatusCode <- 500 + let body = Encoding.UTF8.GetBytes e.Message + response.OutputStream.Write(body, 0, body.Length) + finally + response.OutputStream.Close() + +let serve (port: int) = + let root = Path.GetFullPath htmlOutput + let url = sprintf "http://localhost:%d/" port + + let listener = new HttpListener() + listener.Prefixes.Add(sprintf "http://localhost:%d/" port) + try listener.Start() + with :? HttpListenerException -> + failwithf "could not listen on port %d — it is probably already in use. Pass --port ." port + + printfn "" + printfn " documentation serving at %s" url + printfn " ctrl-c to stop; re-run './build.sh docs' to pick up edits" + printfn "" + + let headless = + [ "CI"; "TF_BUILD"; "GITHUB_ACTIONS" ] + |> List.exists (fun v -> not (String.IsNullOrEmpty(Environment.GetEnvironmentVariable v))) + if not headless then + try + let opener, a = + if OperatingSystem.IsMacOS() then "open", url + elif OperatingSystem.IsWindows() then "cmd", sprintf "/c start %s" url + else "xdg-open", url + Diagnostics.ProcessStartInfo(opener, Arguments = a, UseShellExecute = false) + |> Diagnostics.Process.Start + |> ignore + with _ -> () + + let mutable running = true + Console.CancelKeyPress.Add(fun e -> + e.Cancel <- true + running <- false + listener.Stop()) + + while running do + try + let context = listener.GetContext() + Task.Run(fun () -> handle root context) |> ignore + with + | :? HttpListenerException -> () + | :? ObjectDisposedException -> () + + (listener :> IDisposable).Dispose() + printfn "stopped" diff --git a/build/scripts/Targets.fs b/build/scripts/Targets.fs index 7875b8a..0d2eef8 100644 --- a/build/scripts/Targets.fs +++ b/build/scripts/Targets.fs @@ -163,6 +163,11 @@ let private validateSchema (arguments:ParseResults) = finally if File.Exists tempPath then File.Delete tempPath +let private docs (arguments:ParseResults) = + Documentation.build () + let port = 8080 + Documentation.serve port + let private release (arguments:ParseResults) = printfn "release" let private publish (arguments:ParseResults) = printfn "publish" @@ -185,6 +190,7 @@ let Setup (parsed:ParseResults) (subCommand:Arguments) = step UpdateSchema.Name updateSchema step ValidateSchema.Name validateSchema + step Docs.Name docs cmd Test.Name (Some [Build.Name;]) None <| fun _ -> test parsed diff --git a/build/scripts/scripts.fsproj b/build/scripts/scripts.fsproj index b388460..e463abb 100644 --- a/build/scripts/scripts.fsproj +++ b/build/scripts/scripts.fsproj @@ -16,6 +16,7 @@ + diff --git a/docs/CNAME b/docs/CNAME new file mode 100644 index 0000000..9a30168 --- /dev/null +++ b/docs/CNAME @@ -0,0 +1 @@ +argh.nullean.net diff --git a/docs/_docset.yml b/docs/_docset.yml index d899ec9..852f784 100644 --- a/docs/_docset.yml +++ b/docs/_docset.yml @@ -2,7 +2,7 @@ project: argh max_toc_depth: 2 branding: - icon: assets/logo.svg + icon: images/argh-mark.svg toc: - file: index.md diff --git a/docs/argh-landing.html b/docs/argh-landing.html new file mode 100644 index 0000000..15cec62 --- /dev/null +++ b/docs/argh-landing.html @@ -0,0 +1,748 @@ + + + + + +Nullean.Argh — source-generated .NET CLIs + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+ .NET · source-generated · AOT-safe +

Write methods.
Get a CLI.

+

+ Methods become commands, XML docs become help text, records become option sets. + A Roslyn source generator emits parsing, routing, and dispatch directly into your assembly + — no reflection, no runtime overhead, trimming- and AOT-safe from day one. +

+
+
+ + nuget ↗ +
+
+ + nuget ↗ +
+
+ +
+ +
+
+ + mytool --help +
+
+
$ mytool --help
+
 
+
Usage: mytool <command> [options]
+
 
+
Commands:
+
  deploy Deploy a release to an environment
+
  rollback Roll back to the previous version
+
  status Show current deployment status
+
 
+
$ mytool deploy --help
+
 
+
Usage: mytool deploy [options]
+
  Deploy a release to an environment.
+
 
+
  --env <string> Target environment [required]
+
  --version <string> Release version tag
+
  --dry-run <bool> Simulate without applying
+
 
+
$
+
+
+
+
+ +
+ + +
+
+ +

Everything a CLI needs.
None of the plumbing.

+

+ The generator emits a typed dispatch tree, option parsers, help printers, and completion + tables directly into your assembly at build time. Nothing to configure at runtime, + nothing that can go wrong at startup. +

+ + +
+
+ +
+ + +
+
+ +

The full picture.

+

+ Everything you expect from a modern .NET CLI framework — generated at build time so + none of it costs startup time or binary size. +

+ +
    +
  • DTO binding with [AsParameters] — records and classes expand into flags without a custom bind loop
  • +
  • DataAnnotations validation — [Range], [StringLength], [AllowedValues] — constraints appear in --help, failures exit 2
  • +
  • Fuzzy matching — typos produce actionable errors with ranked suggestions
  • +
  • CancellationToken injection — add it to a handler and it tracks Ctrl+C or host shutdown
  • +
  • Middleware pipeline — cross-cutting concerns wired once, applied to every command
  • +
  • Global and namespace options — flags that apply to a whole tree, parsed once, injected everywhere
  • +
  • Microsoft.Extensions.Hosting — Nullean.Argh.Hosting plugs into IHost and DI with one call
  • +
  • Zero dep or ME.* native — Nullean.Argh has no Microsoft.Extensions.* dependency
  • +
+
+
+ +
+ + +
+
+ +

One package.
Then write methods.

+

+ Two entry points depending on whether you need DI. Either way, registration is a single + method call per command — the generator does the rest. +

+ +
+
+
+
+
01
+
+
Add the package
+

Console apps use Nullean.Argh. Hosted apps with DI use Nullean.Argh.Hosting. Everything else is pulled in transitively.

+
+
+
+
02
+
+
Map your handlers
+

Method groups, lambdas, or whole classes. The generator discovers every registration at build time and emits typed dispatch code.

+
+
+
+
03
+
+
Document with XML docs
+

Add <summary> and <param> tags to your methods. That is your help text — no duplication, no string literals.

+
+
+
+
+ +
+
+
console app
+
using Nullean.Argh;
+
+var app = new ArghApp();
+app.Map("deploy", DeployHandlers.Run);
+app.Map("status", StatusHandlers.Show);
+
+return await app.RunAsync(args);
+
+ +
+
handler with xml docs
+
/// <summary>Deploy a release to an environment.</summary>
+/// <param name="env">Target environment.</param>
+/// <param name="dryRun">Simulate without applying.</param>
+public static async Task<int> Run(
+    string env,
+    bool dryRun = false)
+{
+    // --env and --dry-run are generated
+    return 0;
+}
+
+ +
+
hosted app (DI)
+
using Nullean.Argh.Hosting;
+
+var builder = Host.CreateApplicationBuilder(args);
+builder.Services.AddArgh(args, b =>
+    b.Map("deploy", DeployHandlers.Run));
+await builder.Build().RunAsync();
+
+
+
+
+
+ +
+ + +
+ +
+ + +
+
+

Write the method.
Ship the CLI.

+

One package. XML docs you already write. A source generator that handles everything else.

+ +
+
+ + + + + +
+ + diff --git a/docs/images/argh-lockup-animated.svg b/docs/images/argh-lockup-animated.svg new file mode 100644 index 0000000..4cd4d8b --- /dev/null +++ b/docs/images/argh-lockup-animated.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + -- + argh + _ + + \ No newline at end of file diff --git a/docs/images/argh-lockup-light-animated.svg b/docs/images/argh-lockup-light-animated.svg new file mode 100644 index 0000000..d85f6b9 --- /dev/null +++ b/docs/images/argh-lockup-light-animated.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + -- + argh + _ + + \ No newline at end of file diff --git a/docs/images/argh-lockup-light.svg b/docs/images/argh-lockup-light.svg new file mode 100644 index 0000000..5f3e640 --- /dev/null +++ b/docs/images/argh-lockup-light.svg @@ -0,0 +1,13 @@ + + + + + + + + + -- + argh + _ + + \ No newline at end of file diff --git a/docs/images/argh-lockup.svg b/docs/images/argh-lockup.svg new file mode 100644 index 0000000..5454c33 --- /dev/null +++ b/docs/images/argh-lockup.svg @@ -0,0 +1,13 @@ + + + + + + + + + -- + argh + _ + + \ No newline at end of file diff --git a/docs/images/argh-mark-animated.svg b/docs/images/argh-mark-animated.svg new file mode 100644 index 0000000..7ce682d --- /dev/null +++ b/docs/images/argh-mark-animated.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + - + a + + \ No newline at end of file diff --git a/docs/images/argh-mark-light-animated.svg b/docs/images/argh-mark-light-animated.svg new file mode 100644 index 0000000..9a4c0e4 --- /dev/null +++ b/docs/images/argh-mark-light-animated.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + - + a + + \ No newline at end of file diff --git a/docs/images/argh-mark-light.svg b/docs/images/argh-mark-light.svg new file mode 100644 index 0000000..f18fa8b --- /dev/null +++ b/docs/images/argh-mark-light.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + - + a + + \ No newline at end of file diff --git a/docs/images/argh-mark.svg b/docs/images/argh-mark.svg new file mode 100644 index 0000000..8670bc2 --- /dev/null +++ b/docs/images/argh-mark.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + - + a + + \ No newline at end of file diff --git a/docs/images/png/argh-lockup-174x96.png b/docs/images/png/argh-lockup-174x96.png new file mode 100644 index 0000000..5c3f8c4 Binary files /dev/null and b/docs/images/png/argh-lockup-174x96.png differ diff --git a/docs/images/png/argh-lockup-348x192.png b/docs/images/png/argh-lockup-348x192.png new file mode 100644 index 0000000..3c7ea63 Binary files /dev/null and b/docs/images/png/argh-lockup-348x192.png differ diff --git a/docs/images/png/argh-lockup-696x384.png b/docs/images/png/argh-lockup-696x384.png new file mode 100644 index 0000000..8d1ea13 Binary files /dev/null and b/docs/images/png/argh-lockup-696x384.png differ diff --git a/docs/images/png/argh-lockup-light-174x96.png b/docs/images/png/argh-lockup-light-174x96.png new file mode 100644 index 0000000..4144029 Binary files /dev/null and b/docs/images/png/argh-lockup-light-174x96.png differ diff --git a/docs/images/png/argh-lockup-light-348x192.png b/docs/images/png/argh-lockup-light-348x192.png new file mode 100644 index 0000000..19938a7 Binary files /dev/null and b/docs/images/png/argh-lockup-light-348x192.png differ diff --git a/docs/images/png/argh-lockup-light-696x384.png b/docs/images/png/argh-lockup-light-696x384.png new file mode 100644 index 0000000..822932e Binary files /dev/null and b/docs/images/png/argh-lockup-light-696x384.png differ diff --git a/docs/images/png/argh-mark-1024.png b/docs/images/png/argh-mark-1024.png new file mode 100644 index 0000000..5fcefbc Binary files /dev/null and b/docs/images/png/argh-mark-1024.png differ diff --git a/docs/images/png/argh-mark-128.png b/docs/images/png/argh-mark-128.png new file mode 100644 index 0000000..f474196 Binary files /dev/null and b/docs/images/png/argh-mark-128.png differ diff --git a/docs/images/png/argh-mark-16.png b/docs/images/png/argh-mark-16.png new file mode 100644 index 0000000..32a79aa Binary files /dev/null and b/docs/images/png/argh-mark-16.png differ diff --git a/docs/images/png/argh-mark-180.png b/docs/images/png/argh-mark-180.png new file mode 100644 index 0000000..c212176 Binary files /dev/null and b/docs/images/png/argh-mark-180.png differ diff --git a/docs/images/png/argh-mark-192.png b/docs/images/png/argh-mark-192.png new file mode 100644 index 0000000..9ce8f93 Binary files /dev/null and b/docs/images/png/argh-mark-192.png differ diff --git a/docs/images/png/argh-mark-20.png b/docs/images/png/argh-mark-20.png new file mode 100644 index 0000000..afbf101 Binary files /dev/null and b/docs/images/png/argh-mark-20.png differ diff --git a/docs/images/png/argh-mark-24.png b/docs/images/png/argh-mark-24.png new file mode 100644 index 0000000..20b1f1d Binary files /dev/null and b/docs/images/png/argh-mark-24.png differ diff --git a/docs/images/png/argh-mark-256.png b/docs/images/png/argh-mark-256.png new file mode 100644 index 0000000..10ceced Binary files /dev/null and b/docs/images/png/argh-mark-256.png differ diff --git a/docs/images/png/argh-mark-32.png b/docs/images/png/argh-mark-32.png new file mode 100644 index 0000000..d9a9bc3 Binary files /dev/null and b/docs/images/png/argh-mark-32.png differ diff --git a/docs/images/png/argh-mark-48.png b/docs/images/png/argh-mark-48.png new file mode 100644 index 0000000..7ee520d Binary files /dev/null and b/docs/images/png/argh-mark-48.png differ diff --git a/docs/images/png/argh-mark-512.png b/docs/images/png/argh-mark-512.png new file mode 100644 index 0000000..916a2ca Binary files /dev/null and b/docs/images/png/argh-mark-512.png differ diff --git a/docs/images/png/argh-mark-64.png b/docs/images/png/argh-mark-64.png new file mode 100644 index 0000000..05da909 Binary files /dev/null and b/docs/images/png/argh-mark-64.png differ diff --git a/docs/images/png/argh-mark-96.png b/docs/images/png/argh-mark-96.png new file mode 100644 index 0000000..646be9f Binary files /dev/null and b/docs/images/png/argh-mark-96.png differ diff --git a/docs/images/png/argh-mark-light-1024.png b/docs/images/png/argh-mark-light-1024.png new file mode 100644 index 0000000..564de67 Binary files /dev/null and b/docs/images/png/argh-mark-light-1024.png differ diff --git a/docs/images/png/argh-mark-light-128.png b/docs/images/png/argh-mark-light-128.png new file mode 100644 index 0000000..b47f372 Binary files /dev/null and b/docs/images/png/argh-mark-light-128.png differ diff --git a/docs/images/png/argh-mark-light-16.png b/docs/images/png/argh-mark-light-16.png new file mode 100644 index 0000000..f8bef31 Binary files /dev/null and b/docs/images/png/argh-mark-light-16.png differ diff --git a/docs/images/png/argh-mark-light-180.png b/docs/images/png/argh-mark-light-180.png new file mode 100644 index 0000000..21194c4 Binary files /dev/null and b/docs/images/png/argh-mark-light-180.png differ diff --git a/docs/images/png/argh-mark-light-192.png b/docs/images/png/argh-mark-light-192.png new file mode 100644 index 0000000..4a497c6 Binary files /dev/null and b/docs/images/png/argh-mark-light-192.png differ diff --git a/docs/images/png/argh-mark-light-20.png b/docs/images/png/argh-mark-light-20.png new file mode 100644 index 0000000..80a8caa Binary files /dev/null and b/docs/images/png/argh-mark-light-20.png differ diff --git a/docs/images/png/argh-mark-light-24.png b/docs/images/png/argh-mark-light-24.png new file mode 100644 index 0000000..4f0546f Binary files /dev/null and b/docs/images/png/argh-mark-light-24.png differ diff --git a/docs/images/png/argh-mark-light-256.png b/docs/images/png/argh-mark-light-256.png new file mode 100644 index 0000000..458e09d Binary files /dev/null and b/docs/images/png/argh-mark-light-256.png differ diff --git a/docs/images/png/argh-mark-light-32.png b/docs/images/png/argh-mark-light-32.png new file mode 100644 index 0000000..69c8c42 Binary files /dev/null and b/docs/images/png/argh-mark-light-32.png differ diff --git a/docs/images/png/argh-mark-light-48.png b/docs/images/png/argh-mark-light-48.png new file mode 100644 index 0000000..77b70a1 Binary files /dev/null and b/docs/images/png/argh-mark-light-48.png differ diff --git a/docs/images/png/argh-mark-light-512.png b/docs/images/png/argh-mark-light-512.png new file mode 100644 index 0000000..2b5adfe Binary files /dev/null and b/docs/images/png/argh-mark-light-512.png differ diff --git a/docs/images/png/argh-mark-light-64.png b/docs/images/png/argh-mark-light-64.png new file mode 100644 index 0000000..2bb0e1f Binary files /dev/null and b/docs/images/png/argh-mark-light-64.png differ diff --git a/docs/images/png/argh-mark-light-96.png b/docs/images/png/argh-mark-light-96.png new file mode 100644 index 0000000..f84e50c Binary files /dev/null and b/docs/images/png/argh-mark-light-96.png differ diff --git a/nuget-icon.png b/nuget-icon.png index 2adb353..10ceced 100644 Binary files a/nuget-icon.png and b/nuget-icon.png differ diff --git a/src/Nullean.Argh.Hosting/README.md b/src/Nullean.Argh.Hosting/README.md index 69f2e7a..2b1a52d 100644 --- a/src/Nullean.Argh.Hosting/README.md +++ b/src/Nullean.Argh.Hosting/README.md @@ -1,3 +1,5 @@ +

--argh_

+ # Nullean.Argh.Hosting [![NuGet](https://img.shields.io/nuget/v/Nullean.Argh.Hosting.svg)](https://www.nuget.org/packages/Nullean.Argh.Hosting) diff --git a/src/Nullean.Argh/README.md b/src/Nullean.Argh/README.md index 74cd6d2..a5dc1bf 100644 --- a/src/Nullean.Argh/README.md +++ b/src/Nullean.Argh/README.md @@ -1,3 +1,5 @@ +

--argh_

+ # Nullean.Argh [![NuGet](https://img.shields.io/nuget/v/Nullean.Argh.svg)](https://www.nuget.org/packages/Nullean.Argh)