feat: add a Tools page printer for note merge and print presets
Chapter officers can merge a markdown note onto filtered students, teams, or events and save the recipe. Extra student-note columns are additional fields (any ## … fields heading) so they work as print tokens whether imported or typed by hand. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
namespace Core.Printing;
|
||||
|
||||
/// <summary>
|
||||
/// Builds a case-insensitive token map. Fill order is imported, then entity, then chapter
|
||||
/// so built-in names win over an imported column with the same name.
|
||||
/// </summary>
|
||||
public static class PrintTokenMap
|
||||
{
|
||||
public static Dictionary<string, string> Create() =>
|
||||
new(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public static Dictionary<string, string> Build(
|
||||
IReadOnlyDictionary<string, string?>? imported,
|
||||
IReadOnlyDictionary<string, string?>? entity,
|
||||
IReadOnlyDictionary<string, string?>? chapter)
|
||||
{
|
||||
var map = Create();
|
||||
Apply(map, imported);
|
||||
Apply(map, entity);
|
||||
Apply(map, chapter);
|
||||
return map;
|
||||
}
|
||||
|
||||
public static void Apply(IDictionary<string, string> map, IReadOnlyDictionary<string, string?>? values)
|
||||
{
|
||||
if (values is null)
|
||||
return;
|
||||
|
||||
foreach (var (key, value) in values)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(key))
|
||||
continue;
|
||||
map[key] = Escape(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Treats substituted values as plain text so they cannot change markdown or inject HTML.
|
||||
/// </summary>
|
||||
public static string Escape(string? value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
return string.Empty;
|
||||
|
||||
return value
|
||||
.Replace("\\", "\\\\", StringComparison.Ordinal)
|
||||
.Replace("*", "\\*", StringComparison.Ordinal)
|
||||
.Replace("_", "\\_", StringComparison.Ordinal)
|
||||
.Replace("`", "\\`", StringComparison.Ordinal)
|
||||
.Replace("[", "\\[", StringComparison.Ordinal)
|
||||
.Replace("]", "\\]", StringComparison.Ordinal)
|
||||
.Replace("<", "<", StringComparison.Ordinal)
|
||||
.Replace(">", ">", StringComparison.Ordinal);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user