feat(cv): rebuild professional resume studio

This commit is contained in:
cesnimda
2026-08-24 20:21:23 +02:00
parent dca5daa1a2
commit 367b70681a
27 changed files with 827 additions and 187 deletions
@@ -94,6 +94,8 @@ public static class StructuredCvProfileJson
profile.Contact.Location = TrimOrNull(profile.Contact.Location);
profile.Contact.Website = TrimOrNull(profile.Contact.Website);
profile.Contact.LinkedIn = TrimOrNull(profile.Contact.LinkedIn);
profile.Contact.GitHub = NormalizeExternalLink(profile.Contact.GitHub);
profile.Contact.Links = NormalizeLinks(profile.Contact.Links);
profile.Summary = CleanList(profile.Summary);
profile.Jobs = (profile.Jobs ?? new List<StructuredCvJob>())
@@ -213,6 +215,11 @@ public static class StructuredCvProfileJson
primary.Contact.Location ??= secondary.Contact.Location;
primary.Contact.Website ??= secondary.Contact.Website;
primary.Contact.LinkedIn ??= secondary.Contact.LinkedIn;
primary.Contact.GitHub ??= secondary.Contact.GitHub;
primary.Contact.Links ??= new();
foreach (var link in secondary.Contact.Links ?? new())
if (!primary.Contact.Links.Any(existing => string.Equals(existing.Url, link.Url, StringComparison.OrdinalIgnoreCase)))
primary.Contact.Links.Add(link);
primary.Summary = primary.Summary.Count == 0
? secondary.Summary
@@ -393,9 +400,20 @@ public static class StructuredCvProfileJson
contact.Location = NormalizeLocationValue(contact.Location);
contact.Website = NormalizeWebsite(contact.Website);
contact.LinkedIn = NormalizeLinkedIn(contact.LinkedIn);
contact.GitHub = NormalizeExternalLink(contact.GitHub);
contact.Links = NormalizeLinks(contact.Links);
return contact;
}
private static List<StructuredCvLink> NormalizeLinks(List<StructuredCvLink>? links) =>
(links ?? new List<StructuredCvLink>())
.Select(link => new StructuredCvLink { Label = TrimOrNull(link?.Label), Url = NormalizeExternalLink(link?.Url) })
.Where(link => link.Url is not null)
.GroupBy(link => link.Url, StringComparer.OrdinalIgnoreCase)
.Select(group => group.First())
.Take(12)
.ToList();
private static StructuredCvJob NormalizeJob(StructuredCvJob? job)
{
job ??= new StructuredCvJob();
@@ -537,6 +555,16 @@ public static class StructuredCvProfileJson
return $"https://www.linkedin.com{path}";
}
private static string? NormalizeExternalLink(string? value)
{
var trimmed = TrimOrNull(value);
if (trimmed is null) return null;
var candidate = trimmed.Contains("://", StringComparison.Ordinal) ? trimmed : $"https://{trimmed}";
if (!Uri.TryCreate(candidate, UriKind.Absolute, out var uri)) return null;
if (uri.Scheme is not ("http" or "https") || string.IsNullOrWhiteSpace(uri.Host) || !string.IsNullOrEmpty(uri.UserInfo)) return null;
return uri.AbsoluteUri.TrimEnd('/');
}
private static string? NormalizeDateValue(string? value)
{
var trimmed = TrimOrNull(value);
@@ -726,6 +754,8 @@ public static class StructuredCvProfileJson
AddIf(contactLines, profile.Contact.Location);
AddIf(contactLines, profile.Contact.Website);
AddIf(contactLines, profile.Contact.LinkedIn);
AddIf(contactLines, profile.Contact.GitHub);
foreach (var link in profile.Contact.Links) AddIf(contactLines, link.Url);
AddSectionIfAny(sections, "Contact", contactLines);
AddSectionIfAny(sections, "Professional Summary", profile.Summary);