feat(cv): extend templates and extraction

This commit is contained in:
cesnimda
2026-08-27 15:27:48 +02:00
parent cc76f86482
commit ccd0af908c
15 changed files with 586 additions and 54 deletions
+29 -2
View File
@@ -34,7 +34,8 @@ public sealed class CvVariantSettings
public double? EntryGapMm { get; set; }
public string? HeadingStyle { get; set; } // caps-rule | underline | plain | bar
public string? HeaderStyle { get; set; } // plain | band | centered | kicker
public string? SkillsStyle { get; set; } // tags | text
public string? SkillsStyle { get; set; } // tags | text | bullets | grouped
public List<CvSkillGroupSetting>? SkillGroups { get; set; }
public string? Layout { get; set; } // single | sidebar-left | sidebar-right | header-band
public double? SidebarWidthMm { get; set; }
public List<string>? SidebarSections { get; set; }
@@ -62,6 +63,9 @@ public sealed class CvSectionSetting
// master order and come last. Null => master profile order. Lets a variant reorder entries without
// touching the master profile.
public List<string>? ItemOrder { get; set; }
// Optional CV-specific content for bullet/tag sections. Null uses master data; an empty list is
// an intentional empty override. Entry sections continue to use stable per-item overrides.
public List<string>? Items { get; set; }
}
public sealed class CvItemOverride
@@ -78,6 +82,14 @@ public sealed class CvCustomSectionSetting
public string? Title { get; set; }
public List<string> Items { get; set; } = new();
public bool Hidden { get; set; }
public string? PresetKey { get; set; }
public string? ContentType { get; set; } // paragraphs | bullets | entries
}
public sealed class CvSkillGroupSetting
{
public string Name { get; set; } = string.Empty;
public List<string> Items { get; set; } = new();
}
public static class CvVariantSettingsJson
@@ -128,7 +140,7 @@ public static class CvVariantSettingsJson
s.SidebarWidthMm = Clamp(s.SidebarWidthMm, 45, 85);
s.HeadingStyle = NormalizeChoice(s.HeadingStyle, "caps-rule", "underline", "plain", "bar");
s.HeaderStyle = NormalizeChoice(s.HeaderStyle, "plain", "band", "centered", "kicker");
s.SkillsStyle = NormalizeChoice(s.SkillsStyle, "tags", "text");
s.SkillsStyle = NormalizeChoice(s.SkillsStyle, "tags", "text", "bullets", "grouped");
s.Layout = NormalizeChoice(s.Layout, "single", "sidebar-left", "sidebar-right", "header-band");
s.DateFormat = NormalizeChoice(s.DateFormat, "long", "short", "numeric", "year");
if (!string.IsNullOrWhiteSpace(s.Language))
@@ -146,6 +158,21 @@ public static class CvVariantSettingsJson
s.Sections ??= new();
s.Overrides ??= new();
s.CustomSections ??= new();
s.SkillGroups = s.SkillGroups?
.Where(group => !string.IsNullOrWhiteSpace(group.Name) || group.Items.Any(item => !string.IsNullOrWhiteSpace(item)))
.Take(30)
.Select(group => new CvSkillGroupSetting
{
Name = (group.Name ?? string.Empty).Trim(),
Items = group.Items.Where(item => !string.IsNullOrWhiteSpace(item)).Select(item => item.Trim()).Distinct(StringComparer.OrdinalIgnoreCase).Take(100).ToList(),
})
.ToList();
foreach (var section in s.CustomSections)
{
section.ContentType = NormalizeChoice(section.ContentType, "paragraphs", "bullets", "entries") ?? "bullets";
section.PresetKey = string.IsNullOrWhiteSpace(section.PresetKey) ? null : section.PresetKey.Trim().ToLowerInvariant();
section.Items ??= new();
}
return s;
}