package classes import ( "path" "regexp" "strings" ) // MaxMediaStem is the longest file name stem MediaFileName keeps (D-85). const MaxMediaStem = 80 // mediaExtPattern is an extension MediaFileName keeps. var mediaExtPattern = regexp.MustCompile(`^\.[a-z0-9]+$`) // polishLetters transliterates the Polish diacritics (lower case). var polishLetters = map[rune]rune{'ą': 'a', 'ć': 'c', 'ę': 'e', 'ł': 'l', 'ń': 'n', 'ó': 'o', 'ś': 's', 'ź': 'z', 'ż': 'z'} // MediaFileName is the stored name of an uploaded image (D-85, the Blog // Editor's J4 rule, applied on the server whatever the client sends): the // base name's stem lowercased, Polish diacritics transliterated, every other // run of characters outside a-z and 0-9 turned into one hyphen, trimmed and // cut to MaxMediaStem characters, "image" when nothing is left; and its // extension lowercased when it is a dot and letters or digits (dropped // otherwise). "Lwia Grzywa – w lesie!.JPG" is "lwia-grzywa-w-lesie.jpg". // The result needs no escaping in a URL or an src attribute. func MediaFileName(name string) string { base := path.Base(strings.ReplaceAll(name, `\`, "/")) if base == "." || base == "/" { base = "" } stem, ext := base, "" if dot := strings.LastIndexByte(base, '.'); dot >= 0 { if e := strings.ToLower(base[dot:]); mediaExtPattern.MatchString(e) { stem, ext = base[:dot], e } } var b strings.Builder dash := false for _, r := range strings.ToLower(stem) { if t, ok := polishLetters[r]; ok { r = t } if (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') { b.WriteRune(r) dash = false continue } if !dash { b.WriteByte('-') dash = true } } out := strings.Trim(b.String(), "-") if len(out) > MaxMediaStem { out = strings.TrimRight(out[:MaxMediaStem], "-") } if out == "" { out = "image" } return out + ext }