diff --git a/internal/topdata/wiki_deploy_test.go b/internal/topdata/wiki_deploy_test.go index 9b96eec..c8c18cd 100644 --- a/internal/topdata/wiki_deploy_test.go +++ b/internal/topdata/wiki_deploy_test.go @@ -170,11 +170,13 @@ func TestMatchExistingNodeBBPagePrefersGeneratedPublicSlug(t *testing.T) { func TestDeploySlugifyWikiTitleMatchesGeneratedSlugPolicy(t *testing.T) { tests := map[string]string{ - `Grandmaster's Battle Momentum`: "grandmasters-battle-momentum", - `Bigby’s Clenched Fist`: "bigbys-clenched-fist", - `Hardiness vs. Enchantments`: "hardiness-vs-enchantments", - `Clairaudience/Clairvoyance`: "clairaudience-clairvoyance", - `Élite & Noble Houses`: "elite-noble-houses", + `Grandmaster's Battle Momentum`: "grandmasters-battle-momentum", + `Bigby’s Clenched Fist`: "bigbys-clenched-fist", + `Hardiness vs. Enchantments`: "hardiness-vs-enchantments", + `Clairaudience/Clairvoyance`: "clairaudience-clairvoyance", + `Élite & Noble Houses`: "elite-noble-houses", + `Alpha!@#$%^&*()[]-=_+/?.,<>` + "`" + `~|\Omega`: "alpha-omega", + `Æther Œuvre Øresund Straße Þorn Łódź Đelta`: "aether-oeuvre-oresund-strasse-thorn-lodz-delta", } for input, want := range tests { if got := slugifyWikiTitle(input); got != want { diff --git a/internal/topdata/wiki_native_test.go b/internal/topdata/wiki_native_test.go index 9c92548..42807c6 100644 --- a/internal/topdata/wiki_native_test.go +++ b/internal/topdata/wiki_native_test.go @@ -1241,15 +1241,17 @@ func TestWikiPageSlugOverridesChangeTargets(t *testing.T) { func TestWikiSlugifyTitleNormalizesPunctuationAndSeparators(t *testing.T) { tests := map[string]string{ - `Grandmaster's Battle Momentum`: "grandmasters-battle-momentum", - `Bigby’s Clenched Fist`: "bigbys-clenched-fist", - `"Quoted" ‘Curly’ “Title”`: "quoted-curly-title", - `Hardiness vs. Enchantments`: "hardiness-vs-enchantments", - `Clairaudience/Clairvoyance`: "clairaudience-clairvoyance", - `Moon-on-a-Stick`: "moon-on-a-stick", - `Élite & Noble Houses`: "elite-noble-houses", - `Rock 'n' Roll`: "rock-n-roll", - `Melf's Acid Arrow`: "melfs-acid-arrow", + `Grandmaster's Battle Momentum`: "grandmasters-battle-momentum", + `Bigby’s Clenched Fist`: "bigbys-clenched-fist", + `"Quoted" ‘Curly’ “Title”`: "quoted-curly-title", + `Hardiness vs. Enchantments`: "hardiness-vs-enchantments", + `Clairaudience/Clairvoyance`: "clairaudience-clairvoyance", + `Moon-on-a-Stick`: "moon-on-a-stick", + `Élite & Noble Houses`: "elite-noble-houses", + `Rock 'n' Roll`: "rock-n-roll", + `Melf's Acid Arrow`: "melfs-acid-arrow", + `Alpha!@#$%^&*()[]-=_+/?.,<>` + "`" + `~|\Omega`: "alpha-omega", + `Æther Œuvre Øresund Straße Þorn Łódź Đelta`: "aether-oeuvre-oresund-strasse-thorn-lodz-delta", } for input, want := range tests { if got := wikiSlugifyTitle(input); got != want { diff --git a/internal/topdata/wiki_slug.go b/internal/topdata/wiki_slug.go index 0e1a1cf..70be3fa 100644 --- a/internal/topdata/wiki_slug.go +++ b/internal/topdata/wiki_slug.go @@ -13,6 +13,7 @@ func slugifyWikiText(value string, fallback string) string { var b strings.Builder lastDash := false for _, r := range norm.NFKD.String(strings.ToLower(value)) { + transliterated := transliterateWikiSlugRune(r) switch { case r >= 'a' && r <= 'z': b.WriteRune(r) @@ -24,6 +25,9 @@ func slugifyWikiText(value string, fallback string) string { continue case isWikiSlugJoinerPunctuation(r): continue + case transliterated != "": + b.WriteString(transliterated) + lastDash = false default: if b.Len() > 0 && !lastDash { b.WriteByte('-') @@ -46,3 +50,32 @@ func isWikiSlugJoinerPunctuation(r rune) bool { return false } } + +func transliterateWikiSlugRune(r rune) string { + switch r { + case 'æ': + return "ae" + case 'œ': + return "oe" + case 'ø': + return "o" + case 'ß': + return "ss" + case 'þ': + return "th" + case 'ð', 'đ': + return "d" + case 'ł': + return "l" + case 'ħ': + return "h" + case 'ı': + return "i" + case 'ŋ': + return "n" + case 'ŧ': + return "t" + default: + return "" + } +}