60 lines
2.7 KiB
C#
60 lines
2.7 KiB
C#
|
|
using System.Globalization;
|
|||
|
|
using System.Text;
|
|||
|
|
using System.Text.RegularExpressions;
|
|||
|
|
|
|||
|
|
namespace wp2ghost
|
|||
|
|
{
|
|||
|
|
// =============================================================================
|
|||
|
|
// SlugHelper — WordPress-Slugs in saubere Ghost-Slugs (nur a-z, 0-9, "-") umwandeln
|
|||
|
|
// =============================================================================
|
|||
|
|
static class SlugHelper
|
|||
|
|
{
|
|||
|
|
// Griechisch → Latein (Akzente werden vorher abgetrennt)
|
|||
|
|
private static readonly Dictionary<char, string> GreekToLatin = new()
|
|||
|
|
{
|
|||
|
|
['α'] = "a", ['β'] = "v", ['γ'] = "g", ['δ'] = "d", ['ε'] = "e", ['ζ'] = "z", ['η'] = "i", ['θ'] = "th",
|
|||
|
|
['ι'] = "i", ['κ'] = "k", ['λ'] = "l", ['μ'] = "m", ['ν'] = "n", ['ξ'] = "x", ['ο'] = "o", ['π'] = "p",
|
|||
|
|
['ρ'] = "r", ['σ'] = "s", ['ς'] = "s", ['τ'] = "t", ['υ'] = "y", ['φ'] = "f", ['χ'] = "ch", ['ψ'] = "ps", ['ω'] = "o"
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
private static readonly Dictionary<char, string> GermanToLatin = new()
|
|||
|
|
{
|
|||
|
|
['ä'] = "ae", ['ö'] = "oe", ['ü'] = "ue", ['ß'] = "ss"
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// WordPress speichert nicht-lateinische Zeichen im Slug prozentkodiert
|
|||
|
|
/// ("%ce%b3%ce%b9%ce%b1" = "για"). Die Kodierung wird aufgelöst, Griechisch nach Latein
|
|||
|
|
/// umgeschrieben ("gia") und alles übrige auf a-z, 0-9 und "-" reduziert.
|
|||
|
|
/// </summary>
|
|||
|
|
public static string Clean(string? wpSlug, string fallback)
|
|||
|
|
{
|
|||
|
|
string slug = wpSlug ?? "";
|
|||
|
|
try { slug = Uri.UnescapeDataString(slug); } catch { }
|
|||
|
|
|
|||
|
|
// Reste einer abgeschnittenen Kodierung entfernen (WordPress kürzt lange Slugs mitten im Zeichen)
|
|||
|
|
slug = Regex.Replace(slug, "%[0-9a-fA-F]{0,2}", "");
|
|||
|
|
slug = slug.Replace('<27>', '-').ToLowerInvariant();
|
|||
|
|
|
|||
|
|
foreach (var (german, latin) in GermanToLatin)
|
|||
|
|
slug = slug.Replace(german.ToString(), latin);
|
|||
|
|
|
|||
|
|
// Akzente abtrennen: "ί" → "ι", "é" → "e"
|
|||
|
|
slug = string.Concat(slug.Normalize(NormalizationForm.FormD)
|
|||
|
|
.Where(c => CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark));
|
|||
|
|
slug = slug.Replace("ου", "ou");
|
|||
|
|
|
|||
|
|
var result = new StringBuilder();
|
|||
|
|
foreach (char c in slug)
|
|||
|
|
{
|
|||
|
|
if (GreekToLatin.TryGetValue(c, out string? latin)) result.Append(latin);
|
|||
|
|
else if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) result.Append(c);
|
|||
|
|
else result.Append('-');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
string cleaned = Regex.Replace(result.ToString(), "-{2,}", "-").Trim('-');
|
|||
|
|
return cleaned.Length > 0 ? cleaned : fallback;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|