NoteLinkHelper inserts wikilinks into an existing 'Siehe auch' section
or appends one. ApplyPlaceholders fills {{title}}/{{date}}/{{topic}} in
template bodies. new --template <name> fetches a server-side template
before opening the editor. SlugGuard moved to NozCli.Core in a previous
session — remove stale copy from NozCli.
60 lines
2.5 KiB
C#
60 lines
2.5 KiB
C#
using System.Text.RegularExpressions;
|
|
|
|
namespace NozCli.Core.Client;
|
|
|
|
public static class NoteLinkHelper
|
|
{
|
|
/// Inserts a wikilink to <paramref name="targetSlug"/> into <paramref name="markdown"/>.
|
|
/// Appends to an existing section matching <paramref name="sectionHeader"/>,
|
|
/// or creates that section at the end of the note if absent.
|
|
public static string AddLink(string markdown, string targetSlug, string sectionHeader = "Siehe auch")
|
|
{
|
|
var link = $"- [[{targetSlug}]]";
|
|
|
|
// Find the section heading (## Siehe auch, ## See also, etc.)
|
|
var sectionMatch = Regex.Match(
|
|
markdown,
|
|
$@"(?m)^##\s+{Regex.Escape(sectionHeader)}\s*$",
|
|
RegexOptions.IgnoreCase);
|
|
|
|
if (sectionMatch.Success)
|
|
{
|
|
// Already has this link?
|
|
if (markdown.Contains($"[[{targetSlug}]]", StringComparison.Ordinal))
|
|
return markdown;
|
|
|
|
// Insert at the end of this section's content (before next ## heading or EOF)
|
|
var afterSection = markdown.IndexOf('\n', sectionMatch.Index + sectionMatch.Length);
|
|
if (afterSection < 0) afterSection = markdown.Length;
|
|
|
|
var nextHeading = Regex.Match(
|
|
markdown[afterSection..],
|
|
@"(?m)^##\s",
|
|
RegexOptions.IgnoreCase);
|
|
|
|
var insertAt = nextHeading.Success
|
|
? afterSection + nextHeading.Index
|
|
: markdown.Length;
|
|
|
|
var before = markdown[..insertAt].TrimEnd();
|
|
var after = markdown[insertAt..];
|
|
|
|
return before + "\n" + link + "\n" + (after.Length > 0 ? "\n" + after.TrimStart() : "");
|
|
}
|
|
|
|
// No section found — create one at the end
|
|
return markdown.TrimEnd() + $"\n\n## {sectionHeader}\n\n{link}\n";
|
|
}
|
|
|
|
/// Replaces template placeholders with actual values.
|
|
public static string ApplyPlaceholders(
|
|
string template, string title, string topic, string lang, string status)
|
|
{
|
|
return template
|
|
.Replace("{{title}}", title, StringComparison.Ordinal)
|
|
.Replace("{{topic}}", topic, StringComparison.Ordinal)
|
|
.Replace("{{lang}}", lang, StringComparison.Ordinal)
|
|
.Replace("{{status}}", status, StringComparison.Ordinal)
|
|
.Replace("{{date}}", DateTime.UtcNow.ToString("yyyy-MM-dd"), StringComparison.Ordinal);
|
|
}
|
|
}
|