What's wrong
PropertyMerger.FindBasicCanonicalName (Frontmatter/PropertyMerger.cs:220-243) pairs two keys whenever one normalized name contains the other (:231-232). It then maps the longer key onto the shorter one through PreferredName.
- Aggressive:
GetAggressiveCanonicalName (:85-96) accepts the pairing when IsInSameCategory(key, canonicalName) holds. That check passes whenever the target is a known name such as title, tag, name, author or url.
- Maximum: accepts the pairing unconditionally (
FindSemanticCanonicalName, :261-265).
Once paired, the two keys form one merge group. For scalar values, MergePropertyGroup keeps only the first value (:152-156), so the other property's value is thrown away without any warning.
Reproduction (HEAD 43a9cdc)
Each row runs CombineFrontmatter("---\n{k1}: A\n{k2}: B\n---\nBody\n", AsIs, AsIs, strategy) and reads back the resulting keys:
| Input keys |
Conservative |
Aggressive |
Maximum |
| title + subtitle |
both kept |
title=A only |
title=A only |
| tag + tagline |
both kept |
tag=A only |
tag=A only |
| name + username |
both kept |
name=A only |
name=A only |
| author + author_url |
both kept |
author=A only |
author=A only |
| url + canonical_url |
both kept |
url=A only |
url=A only |
| summary + summary_image |
both kept |
summary=A only |
summary=A only |
| image + image_alt, version + version_date, step1 + step10 |
both kept |
both kept |
first key only |
At scale, a block of 200 distinct scalars property0 … property199 comes back from Maximum with 10 keys. The other 190 values are gone, because property12 "contains" property1, and so on.
Why it matters
subtitle, tagline, username and canonical_url are separate, common fields in Hugo, Jekyll and Obsidian. A stronger merge strategy should combine synonyms. It should not delete fields that happen to share a substring with another field.
This is related to two open issues, but neither covers it:
Suggested fix / acceptance criteria
- Only let containment pair two keys when the leftover part is known decoration, meaning the
PropertyNameNormalizer prefix and suffix lists. Alternatively, compare whole words instead of raw substrings.
- In Aggressive, require both keys to be in the category, not just the target.
- Acceptance:
- Every pair in the table keeps both values under Aggressive and Maximum.
property0..property199 keeps all 200 keys.
- The existing containment and equivalence tests still pass, or are updated deliberately. This includes
MergeSimilarProperties_WithContainmentSimilarity_MapsCorrectly and the related/page_related tests.
What's wrong
PropertyMerger.FindBasicCanonicalName(Frontmatter/PropertyMerger.cs:220-243) pairs two keys whenever one normalized name contains the other (:231-232). It then maps the longer key onto the shorter one throughPreferredName.GetAggressiveCanonicalName(:85-96) accepts the pairing whenIsInSameCategory(key, canonicalName)holds. That check passes whenever the target is a known name such astitle,tag,name,authororurl.FindSemanticCanonicalName,:261-265).Once paired, the two keys form one merge group. For scalar values,
MergePropertyGroupkeeps only the first value (:152-156), so the other property's value is thrown away without any warning.Reproduction (HEAD 43a9cdc)
Each row runs
CombineFrontmatter("---\n{k1}: A\n{k2}: B\n---\nBody\n", AsIs, AsIs, strategy)and reads back the resulting keys:title=Aonlytitle=Aonlytag=Aonlytag=Aonlyname=Aonlyname=Aonlyauthor=Aonlyauthor=Aonlyurl=Aonlyurl=Aonlysummary=Aonlysummary=AonlyAt scale, a block of 200 distinct scalars
property0…property199comes back from Maximum with 10 keys. The other 190 values are gone, becauseproperty12"contains"property1, and so on.Why it matters
subtitle,tagline,usernameandcanonical_urlare separate, common fields in Hugo, Jekyll and Obsidian. A stronger merge strategy should combine synonyms. It should not delete fields that happen to share a substring with another field.This is related to two open issues, but neither covers it:
author_email→author,previous_version→version#162 is the same containment heuristic inNameStandardizer. There the key is renamed but its value survives; here the value is destroyed.Suggested fix / acceptance criteria
PropertyNameNormalizerprefix and suffix lists. Alternatively, compare whole words instead of raw substrings.property0..property199keeps all 200 keys.MergeSimilarProperties_WithContainmentSimilarity_MapsCorrectlyand therelated/page_relatedtests.