SHA256
webstatic status: Markdown-Rendering im Terminal + LICENSE mit Dep-Lizenzen
- MarkdownConsoleRenderer.cs: eigener Markdig-AST→ANSI-Renderer (keine neue NuGet-Dependency). Unterstützt Headings, Paragraphs, Listen, Code-Blöcke, Blockquotes, Tabellen, Thematic Breaks, Inline-Formatierung (bold/italic/code/links). ANSI-Styling mit Farben. - Program.cs: 'webstatic status' / 'webstatic --status' Subcommand — rendert README.md der Site im Terminal (Default: cwd, --root überschreibt). Graceful error wenn README.md fehlt. Help-Eintrag ergänzt. - LICENSE: Third-Party-Dependency-Lizenzen ergänzt (Markdig BSD-2-Clause, YamlDotNet MIT) mit vollständigen Lizenztexten, Links und Kompatibilitäts-Tabelle. - README.md: aktualisiert als Status-Dokument (neuer status-Befehl, CLI-Befehle-Tabelle, bereinigte Environments, LICENSE-Verweis).
This commit is contained in:
@@ -19,3 +19,73 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Third-Party Dependencies
|
||||||
|
|
||||||
|
This software uses the following third-party NuGet packages. Their license
|
||||||
|
terms apply to the respective portions of the distributed binaries. The source
|
||||||
|
code of GCBoK.WebStaticBuilder itself remains under the MIT license above.
|
||||||
|
|
||||||
|
### Markdig
|
||||||
|
|
||||||
|
- **Package:** Markdig (https://www.nuget.org/packages/Markdig)
|
||||||
|
- **Purpose:** Markdown → HTML rendering (CommonMark compliant, extensible)
|
||||||
|
- **License:** BSD-2-Clause (https://github.com/xoofx/markdig/blob/master/license.txt)
|
||||||
|
- **Copyright:** © Alexandre Mutel (xoofx)
|
||||||
|
- **Repository:** https://github.com/xoofx/markdig
|
||||||
|
|
||||||
|
> Redistribution and use in source and binary forms, with or without
|
||||||
|
> modification, are permitted provided that the following conditions are met:
|
||||||
|
> 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
> this list of conditions and the following disclaimer.
|
||||||
|
> 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
> this list of conditions and the following disclaimer in the documentation
|
||||||
|
> and/or other materials provided with the distribution.
|
||||||
|
>
|
||||||
|
> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
> AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
> IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
> ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
> LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
> CONSEQUENTIAL DAMAGES HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
> WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||||
|
> OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
> ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
### YamlDotNet
|
||||||
|
|
||||||
|
- **Package:** YamlDotNet (https://www.nuget.org/packages/YamlDotNet)
|
||||||
|
- **Purpose:** YAML frontmatter parsing for Markdown content files
|
||||||
|
- **License:** MIT (https://github.com/aaubry/YamlDotNet/blob/master/LICENSE)
|
||||||
|
- **Copyright:** © Antoine Aubry and contributors
|
||||||
|
- **Repository:** https://github.com/aaubry/YamlDotNet
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
### Summary
|
||||||
|
|
||||||
|
| Package | License | Compatible with MIT? |
|
||||||
|
|-------------|---------------|----------------------|
|
||||||
|
| Markdig | BSD-2-Clause | Yes (permissive) |
|
||||||
|
| YamlDotNet | MIT | Yes (same license) |
|
||||||
|
|
||||||
|
Both dependencies are permissive licenses compatible with MIT. No copyleft
|
||||||
|
(GPL/AGPL/LGPL) components are used.
|
||||||
|
|||||||
@@ -6,12 +6,13 @@ früheren C#-Builderskript der GCBoK-Website durch ein generisches, für KMU
|
|||||||
einsetzbares Werkzeug.
|
einsetzbares Werkzeug.
|
||||||
|
|
||||||
- **Sprache:** C# / .NET 10 (kompilierte Konsole)
|
- **Sprache:** C# / .NET 10 (kompilierte Konsole)
|
||||||
- **Lizenz:** MIT
|
- **Lizenz:** MIT (siehe `LICENSE` für Third-Party-Dependency-Lizenzen)
|
||||||
- **Kein Python:** einzige externe Abhängigkeit ist `npx pagefind` (Suchindex, optional)
|
- **Kein Python:** einzige externe Abhängigkeit ist `npx pagefind` (Suchindex, optional)
|
||||||
- **Funktionen:** Markdown + YAML-Frontmatter → statisches HTML pro Sprache,
|
- **Funktionen:** Markdown + YAML-Frontmatter → statisches HTML pro Sprache,
|
||||||
Navigation, SEO-Kopf (OpenGraph/JSON-LD), `sitemap.xml`, `robots.txt`,
|
Navigation, SEO-Kopf (OpenGraph/JSON-LD), `sitemap.xml`, `robots.txt`,
|
||||||
Mermaid-Diagramme, client-seitige Volltextsuche (Pagefind), UI-Lokalisierung
|
Mermaid-Diagramme, client-seitige Volltextsuche (Pagefind), UI-Lokalisierung
|
||||||
über `{{ i18n.* }}`, optionaler Machine-Translation-Helfer (Entwürfe).
|
über `{{ i18n.* }}`, optionaler Machine-Translation-Helfer (Entwürfe),
|
||||||
|
Markdown-Rendering im Terminal via `webstatic status`.
|
||||||
|
|
||||||
## Schnellstart
|
## Schnellstart
|
||||||
|
|
||||||
@@ -26,8 +27,25 @@ dotnet ../../bin/Release/net10.0/webstatic.dll build --env development
|
|||||||
|
|
||||||
# Lokal ansehen
|
# Lokal ansehen
|
||||||
dotnet ../../bin/Release/net10.0/webstatic.dll serve --port 8000
|
dotnet ../../bin/Release/net10.0/webstatic.dll serve --port 8000
|
||||||
|
|
||||||
|
# Site-Status (README.md im Terminal rendern)
|
||||||
|
dotnet ../../bin/Release/net10.0/webstatic.dll status
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## CLI-Befehle
|
||||||
|
|
||||||
|
| Befehl | Bedeutung |
|
||||||
|
|--------|-----------|
|
||||||
|
| `webstatic build [Optionen]` | Website bauen |
|
||||||
|
| `webstatic serve [--port N]` | Lokalen Server starten (Vorschau) |
|
||||||
|
| `webstatic init <name>` | Beispiel-Site anlegen |
|
||||||
|
| `webstatic status [--root DIR]` | README.md der Site im Terminal anzeigen |
|
||||||
|
| `webstatic translate --check` | Fehlende Übersetzungen melden |
|
||||||
|
| `webstatic translate --draft` | Übersetzungs-Entwürfe erzeugen |
|
||||||
|
| `webstatic --version` | Version (Assembly + Git-Commit) anzeigen |
|
||||||
|
| `webstatic --help \| -h` | Hilfe anzeigen |
|
||||||
|
| `webstatic update` | Selbstaktualisierung (Clone-Installation) |
|
||||||
|
|
||||||
## Umgebungen
|
## Umgebungen
|
||||||
|
|
||||||
| `--env` | baseUrl (Beispiel) | Zweck |
|
| `--env` | baseUrl (Beispiel) | Zweck |
|
||||||
@@ -81,4 +99,5 @@ src/ C#-Quellcode (GCBoK.WebStaticBuilder)
|
|||||||
tests/ (künftig) Unit/Integrationstests
|
tests/ (künftig) Unit/Integrationstests
|
||||||
webstatic.example/ Vorlage-Site für KMU
|
webstatic.example/ Vorlage-Site für KMU
|
||||||
install.sh KMU-Installation
|
install.sh KMU-Installation
|
||||||
|
LICENSE MIT + Third-Party-Dependency-Lizenzen
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -0,0 +1,265 @@
|
|||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Markdig;
|
||||||
|
using Markdig.Extensions.Tables;
|
||||||
|
using Markdig.Syntax;
|
||||||
|
using Markdig.Syntax.Inlines;
|
||||||
|
|
||||||
|
namespace GCBoK.WebStaticBuilder;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Renders a Markdig AST to ANSI-styled console output. No external
|
||||||
|
/// dependency beyond Markdig (already referenced). Supports headings,
|
||||||
|
/// paragraphs, lists, code blocks, blockquotes, tables, thematic breaks,
|
||||||
|
/// and inline formatting (bold, italic, code, links).
|
||||||
|
/// </summary>
|
||||||
|
public static class MarkdownConsoleRenderer
|
||||||
|
{
|
||||||
|
// ANSI SGR codes
|
||||||
|
private const string Reset = "\x1b[0m";
|
||||||
|
private const string Bold = "\x1b[1m";
|
||||||
|
private const string Dim = "\x1b[2m";
|
||||||
|
private const string Italic = "\x1b[3m";
|
||||||
|
private const string Underline = "\x1b[4m";
|
||||||
|
private const string FgCyan = "\x1b[36m";
|
||||||
|
private const string FgBrightCyan = "\x1b[96m";
|
||||||
|
private const string FgBrightYellow = "\x1b[93m";
|
||||||
|
private const string FgBrightRed = "\x1b[91m";
|
||||||
|
private const string FgBrightGreen = "\x1b[92m";
|
||||||
|
private const string FgBrightBlack = "\x1b[90m";
|
||||||
|
|
||||||
|
/// <summary>Render a Markdown document to the console.</summary>
|
||||||
|
public static void Render(string markdown, TextWriter writer)
|
||||||
|
{
|
||||||
|
var pipeline = new MarkdownPipelineBuilder()
|
||||||
|
.UseAdvancedExtensions()
|
||||||
|
.Build();
|
||||||
|
var doc = Markdig.Markdown.Parse(markdown, pipeline);
|
||||||
|
RenderBlocks(doc, writer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RenderBlocks(ContainerBlock container, TextWriter w, int indent)
|
||||||
|
{
|
||||||
|
foreach (var block in container)
|
||||||
|
RenderBlock(block, w, indent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RenderBlock(Block block, TextWriter w, int indent)
|
||||||
|
{
|
||||||
|
var pad = new string(' ', indent * 2);
|
||||||
|
switch (block)
|
||||||
|
{
|
||||||
|
case HeadingBlock h:
|
||||||
|
RenderHeading(h, w);
|
||||||
|
break;
|
||||||
|
case ParagraphBlock p:
|
||||||
|
w.WriteLine(pad + RenderInlines(p.Inline!));
|
||||||
|
w.WriteLine();
|
||||||
|
break;
|
||||||
|
case ListBlock lb:
|
||||||
|
RenderList(lb, w, indent);
|
||||||
|
break;
|
||||||
|
case QuoteBlock qb:
|
||||||
|
RenderQuote(qb, w, indent);
|
||||||
|
break;
|
||||||
|
case FencedCodeBlock fc:
|
||||||
|
RenderCodeBlock(fc.Lines.ToString(), w, indent, fc.Info);
|
||||||
|
break;
|
||||||
|
case CodeBlock cb:
|
||||||
|
RenderCodeBlock(cb.Lines.ToString(), w, indent, null);
|
||||||
|
break;
|
||||||
|
case ThematicBreakBlock:
|
||||||
|
w.WriteLine(pad + $"{Dim}{'─'.ToString().PadLeft(Console.BufferWidth > 0 ? Math.Min(Console.BufferWidth, 60) : 60, '─')}{Reset}");
|
||||||
|
w.WriteLine();
|
||||||
|
break;
|
||||||
|
case Table table:
|
||||||
|
RenderTable(table, w, indent);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Fallback: try to extract text content
|
||||||
|
if (block is ContainerBlock cb2)
|
||||||
|
RenderBlocks(cb2, w, indent);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RenderHeading(HeadingBlock h, TextWriter w)
|
||||||
|
{
|
||||||
|
var text = RenderInlines(h.Inline!);
|
||||||
|
var prefix = h.Level switch
|
||||||
|
{
|
||||||
|
1 => $"{Bold}{FgBrightYellow}",
|
||||||
|
2 => $"{Bold}{FgBrightCyan}",
|
||||||
|
3 => $"{Bold}{FgBrightGreen}",
|
||||||
|
_ => $"{Bold}",
|
||||||
|
};
|
||||||
|
w.WriteLine($"{prefix}{text}{Reset}");
|
||||||
|
w.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RenderList(ListBlock lb, TextWriter w, int indent)
|
||||||
|
{
|
||||||
|
var pad = new string(' ', indent * 2);
|
||||||
|
int idx = 1;
|
||||||
|
foreach (ListItemBlock item in lb)
|
||||||
|
{
|
||||||
|
var marker = lb.IsOrdered ? $"{idx}{lb.OrderedDelimiter} " : "• ";
|
||||||
|
var firstBlock = item.FirstOrDefault();
|
||||||
|
if (firstBlock is ParagraphBlock p)
|
||||||
|
{
|
||||||
|
w.WriteLine($"{pad}{marker}{RenderInlines(p.Inline!)}");
|
||||||
|
}
|
||||||
|
else if (firstBlock != null)
|
||||||
|
{
|
||||||
|
w.WriteLine($"{pad}{marker}");
|
||||||
|
RenderBlock(firstBlock, w, indent + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sub-blocks beyond the first paragraph (e.g., nested lists)
|
||||||
|
for (int i = 1; i < item.Count; i++)
|
||||||
|
{
|
||||||
|
if (item[i] is ListBlock subList)
|
||||||
|
RenderList(subList, w, indent + 1);
|
||||||
|
else
|
||||||
|
RenderBlock(item[i], w, indent + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lb.IsOrdered) idx++;
|
||||||
|
}
|
||||||
|
w.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RenderQuote(QuoteBlock qb, TextWriter w, int indent)
|
||||||
|
{
|
||||||
|
var pad = new string(' ', indent * 2);
|
||||||
|
var savedColor = Console.ForegroundColor;
|
||||||
|
Console.ForegroundColor = ConsoleColor.DarkGray;
|
||||||
|
foreach (var sub in qb)
|
||||||
|
{
|
||||||
|
if (sub is ParagraphBlock p)
|
||||||
|
w.WriteLine($"{pad}{Dim}│ {RenderInlines(p.Inline!)}{Reset}");
|
||||||
|
else
|
||||||
|
RenderBlock(sub, w, indent + 1);
|
||||||
|
}
|
||||||
|
Console.ForegroundColor = savedColor;
|
||||||
|
w.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RenderCodeBlock(string code, TextWriter w, int indent, string? lang)
|
||||||
|
{
|
||||||
|
var pad = new string(' ', indent * 2);
|
||||||
|
var lines = code.TrimEnd('\n', '\r').Split('\n');
|
||||||
|
w.WriteLine($"{pad}{Dim}```{lang ?? ""}{Reset}");
|
||||||
|
foreach (var line in lines)
|
||||||
|
w.WriteLine($"{pad}{FgBrightCyan}{line}{Reset}");
|
||||||
|
w.WriteLine($"{pad}{Dim}```{Reset}");
|
||||||
|
w.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RenderTable(Table table, TextWriter w, int indent)
|
||||||
|
{
|
||||||
|
var pad = new string(' ', indent * 2);
|
||||||
|
// First pass: collect cell texts and compute column widths
|
||||||
|
var rows = new List<List<string>>();
|
||||||
|
foreach (TableRow row in table)
|
||||||
|
{
|
||||||
|
var cells = new List<string>();
|
||||||
|
foreach (TableCell cell in row)
|
||||||
|
{
|
||||||
|
var cellText = new StringBuilder();
|
||||||
|
foreach (var sub in cell)
|
||||||
|
{
|
||||||
|
if (sub is ParagraphBlock p)
|
||||||
|
cellText.Append(RenderInlines(p.Inline!));
|
||||||
|
}
|
||||||
|
cells.Add(cellText.ToString().Trim());
|
||||||
|
}
|
||||||
|
rows.Add(cells);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rows.Count == 0) return;
|
||||||
|
var colCount = rows.Max(r => r.Count);
|
||||||
|
var widths = new int[colCount];
|
||||||
|
foreach (var row in rows)
|
||||||
|
for (int c = 0; c < row.Count; c++)
|
||||||
|
widths[c] = Math.Max(widths[c], row[c].Length);
|
||||||
|
|
||||||
|
// Render rows
|
||||||
|
bool isFirstRow = true;
|
||||||
|
foreach (var row in rows)
|
||||||
|
{
|
||||||
|
var parts = new List<string>();
|
||||||
|
for (int c = 0; c < row.Count; c++)
|
||||||
|
{
|
||||||
|
var cellText = c < row.Count ? row[c] : "";
|
||||||
|
var padded = cellText.PadRight(widths[c]);
|
||||||
|
parts.Add(isFirstRow ? $"{Bold}{padded}{Reset}" : padded);
|
||||||
|
}
|
||||||
|
w.WriteLine($"{pad}│ {string.Join(" │ ", parts)} │");
|
||||||
|
|
||||||
|
if (isFirstRow)
|
||||||
|
{
|
||||||
|
// Separator
|
||||||
|
var sep = string.Join("─┬─", widths.Select(wd => new string('─', wd + 2)));
|
||||||
|
w.WriteLine($"{pad}├{sep}┤");
|
||||||
|
isFirstRow = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Render inline elements to a single ANSI-styled string.</summary>
|
||||||
|
private static string RenderInlines(ContainerInline inlines)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
foreach (var il in inlines)
|
||||||
|
RenderInline(il, sb);
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RenderInline(Inline inline, StringBuilder sb)
|
||||||
|
{
|
||||||
|
switch (inline)
|
||||||
|
{
|
||||||
|
case LiteralInline lit:
|
||||||
|
sb.Append(lit.Content.ToString());
|
||||||
|
break;
|
||||||
|
case EmphasisInline emp:
|
||||||
|
var code = emp.DelimiterCount == 2 ? Bold : Italic;
|
||||||
|
sb.Append(code);
|
||||||
|
foreach (var child in emp)
|
||||||
|
RenderInline(child, sb);
|
||||||
|
sb.Append(Reset);
|
||||||
|
if (emp.DelimiterCount == 2) sb.Append(""); // bold doesn't need reset of italic
|
||||||
|
break;
|
||||||
|
case CodeInline ci:
|
||||||
|
sb.Append($"{FgBrightRed}{ci.Content}{Reset}");
|
||||||
|
break;
|
||||||
|
case LinkInline link:
|
||||||
|
var text = new StringBuilder();
|
||||||
|
foreach (var child in link)
|
||||||
|
RenderInline(child, text);
|
||||||
|
if (link.IsImage)
|
||||||
|
sb.Append($"{Dim}[image: {text}{Reset}{Dim}]{Reset}");
|
||||||
|
else if (link.Url != null)
|
||||||
|
sb.Append($"{Underline}{FgCyan}{text}{Reset} {Dim}({link.Url}){Reset}");
|
||||||
|
else
|
||||||
|
sb.Append(text.ToString());
|
||||||
|
break;
|
||||||
|
case LineBreakInline:
|
||||||
|
sb.AppendLine();
|
||||||
|
break;
|
||||||
|
case HtmlInline html:
|
||||||
|
sb.Append($"{Dim}{html.Tag}{Reset}");
|
||||||
|
break;
|
||||||
|
case ContainerInline container:
|
||||||
|
foreach (var child in container)
|
||||||
|
RenderInline(child, sb);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// DelimiterInline, etc. — extract literal content
|
||||||
|
sb.Append(inline.ToString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -96,6 +96,13 @@ if (argsList.Contains("init"))
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Subcommand: status — render the site's README.md to the console
|
||||||
|
if (argsList.Contains("status") || argsList.Contains("--status"))
|
||||||
|
{
|
||||||
|
ShowStatus(root);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Build
|
// Build
|
||||||
// "development" folds work, preview and review into a single local/dev environment.
|
// "development" folds work, preview and review into a single local/dev environment.
|
||||||
var envName = "development";
|
var envName = "development";
|
||||||
@@ -130,6 +137,7 @@ Aufruf:
|
|||||||
webstatic build [Optionen] Website bauen
|
webstatic build [Optionen] Website bauen
|
||||||
webstatic serve [--port N] Lokalen Server starten (Vorschau)
|
webstatic serve [--port N] Lokalen Server starten (Vorschau)
|
||||||
webstatic init <name> Beispiel-Site anlegen
|
webstatic init <name> Beispiel-Site anlegen
|
||||||
|
webstatic status README.md der Site im Terminal anzeigen
|
||||||
webstatic translate --check Fehlende Übersetzungen melden
|
webstatic translate --check Fehlende Übersetzungen melden
|
||||||
webstatic translate --draft Übersetzungs-Entwürfe erzeugen
|
webstatic translate --draft Übersetzungs-Entwürfe erzeugen
|
||||||
webstatic --version Version (Assembly + Git-Commit) anzeigen
|
webstatic --version Version (Assembly + Git-Commit) anzeigen
|
||||||
@@ -382,3 +390,24 @@ static string MimeType(string file)
|
|||||||
_ => "application/octet-stream",
|
_ => "application/octet-stream",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ShowStatus(string rootDir)
|
||||||
|
{
|
||||||
|
// Search for README.md in the site root (case-insensitive)
|
||||||
|
var readme = Directory.GetFiles(rootDir, "README.md", SearchOption.TopDirectoryOnly)
|
||||||
|
.FirstOrDefault()
|
||||||
|
?? Directory.GetFiles(rootDir, "readme.md", SearchOption.TopDirectoryOnly)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (readme == null)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine($"ERROR: no README.md found in {rootDir}");
|
||||||
|
Console.Error.WriteLine(" The status command renders the site's README.md to the console.");
|
||||||
|
Console.Error.WriteLine(" Specify --root <dir> if the site is not in the current directory.");
|
||||||
|
Environment.ExitCode = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var markdown = File.ReadAllText(readme);
|
||||||
|
MarkdownConsoleRenderer.Render(markdown, Console.Out);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user