What's wrong
StandardOrder.PropertyNames holds two camelCase canonical names, redirectFrom and redirectTo (Frontmatter/StandardOrder.cs:184-185). The rest of the library assumes every canonical name is lowercase. The result is that the one input that exactly matches the standard name gets corrupted:
NameStandardizer.StandardizePropertyNames (Frontmatter/NameStandardizer.cs:34-36) sees that the key matches a standard name, ignoring case. It then writes it back as property.Key.ToLowerInvariant() instead of the canonical spelling, so redirectFrom is renamed to redirectfrom.
SortFrontmatterProperties (Frontmatter/Frontmatter.cs:265-270) looks each standard name up case-sensitively. redirectFrom no longer matches the lowercased key, so the property is treated as unknown and goes to the tail, after license, which the standard order puts later.
StandardOrder.Compare (public API, Frontmatter/StandardOrder.cs:220-221) searches the mixed-case array with a.ToLowerInvariant(). It can never find redirectFrom or redirectTo, so it treats them as non-standard names.
Reproduction
Console.WriteLine(Frontmatter.CombineFrontmatter("---\nlicense: MIT\nredirectTo: /new\nzeta: 1\ntitle: Hi\n---\nBody\n"));
Console.WriteLine(StandardOrder.Compare("redirectFrom", "license"));
Actual output (default Standard naming, Sorted, Conservative):
---
title: Hi
license: MIT
redirectto: /new
zeta: 1
---
Body
1
Expected:
---
title: Hi
redirectTo: /new
license: MIT
zeta: 1
---
Body
<negative>
With FrontmatterNaming.AsIs + FrontmatterOrder.Sorted, the same input is ordered correctly (title, redirectTo, license, zeta). So the canonical key is broken only when the caller asks for standardization, and it is the input that already matches the standard name exactly.
Why it matters
Standardization is meant to map variant names onto canonical ones. Here it turns a canonical name into a non-canonical one. Anything that reads the key case-sensitively (static site generators and redirect plugins) no longer sees the redirect, so running CombineFrontmatter with its defaults breaks it without any error. The public StandardOrder.Compare is also wrong for these two names.
Suggested fix / acceptance criteria
- In
NameStandardizer, when a key matches a standard property ignoring case, emit the canonical spelling from StandardOrder.PropertyNames, not ToLowerInvariant(). Either that, or make all canonical names lowercase or snake_case (redirect_from / redirect_to, which Jekyll uses) and keep the list consistent.
StandardOrder.Compare finds the index ignoring case, for example Array.FindIndex(PropertyNames, p => string.Equals(p, a, StringComparison.OrdinalIgnoreCase)).
- Tests:
CombineFrontmatter with redirectFrom: /x keeps the key spelled redirectFrom and orders it before license.
StandardOrder.Compare("redirectFrom", "license") < 0.
- A guard test asserting that every entry in
PropertyNames round-trips unchanged through StandardizePropertyNames.
What's wrong
StandardOrder.PropertyNamesholds two camelCase canonical names,redirectFromandredirectTo(Frontmatter/StandardOrder.cs:184-185). The rest of the library assumes every canonical name is lowercase. The result is that the one input that exactly matches the standard name gets corrupted:NameStandardizer.StandardizePropertyNames(Frontmatter/NameStandardizer.cs:34-36) sees that the key matches a standard name, ignoring case. It then writes it back asproperty.Key.ToLowerInvariant()instead of the canonical spelling, soredirectFromis renamed toredirectfrom.SortFrontmatterProperties(Frontmatter/Frontmatter.cs:265-270) looks each standard name up case-sensitively.redirectFromno longer matches the lowercased key, so the property is treated as unknown and goes to the tail, afterlicense, which the standard order puts later.StandardOrder.Compare(public API,Frontmatter/StandardOrder.cs:220-221) searches the mixed-case array witha.ToLowerInvariant(). It can never findredirectFromorredirectTo, so it treats them as non-standard names.Reproduction
Actual output (default Standard naming, Sorted, Conservative):
Expected:
With
FrontmatterNaming.AsIs+FrontmatterOrder.Sorted, the same input is ordered correctly (title, redirectTo, license, zeta). So the canonical key is broken only when the caller asks for standardization, and it is the input that already matches the standard name exactly.Why it matters
Standardization is meant to map variant names onto canonical ones. Here it turns a canonical name into a non-canonical one. Anything that reads the key case-sensitively (static site generators and redirect plugins) no longer sees the redirect, so running
CombineFrontmatterwith its defaults breaks it without any error. The publicStandardOrder.Compareis also wrong for these two names.Suggested fix / acceptance criteria
NameStandardizer, when a key matches a standard property ignoring case, emit the canonical spelling fromStandardOrder.PropertyNames, notToLowerInvariant(). Either that, or make all canonical names lowercase or snake_case (redirect_from/redirect_to, which Jekyll uses) and keep the list consistent.StandardOrder.Comparefinds the index ignoring case, for exampleArray.FindIndex(PropertyNames, p => string.Equals(p, a, StringComparison.OrdinalIgnoreCase)).CombineFrontmatterwithredirectFrom: /xkeeps the key spelledredirectFromand orders it beforelicense.StandardOrder.Compare("redirectFrom", "license") < 0.PropertyNamesround-trips unchanged throughStandardizePropertyNames.