File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -19,4 +19,5 @@ require (
1919 go.yaml.in/yaml/v3 v3.0.4 // indirect
2020 golang.org/x/crypto v0.46.0 // indirect
2121 golang.org/x/sys v0.39.0 // indirect
22+ golang.org/x/text v0.33.0 // indirect
2223)
Original file line number Diff line number Diff line change @@ -24,6 +24,8 @@ golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
2424golang.org/x/crypto v0.46.0 /go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0 =
2525golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk =
2626golang.org/x/sys v0.39.0 /go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks =
27+ golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE =
28+ golang.org/x/text v0.33.0 /go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8 =
2729gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM =
2830gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 /go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0 =
2931gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA =
Original file line number Diff line number Diff line change 99 "regexp"
1010 "strings"
1111 "time"
12+ "unicode"
13+
14+ "golang.org/x/text/unicode/norm"
1215
1316 "github.com/eljojo/rememory/internal/core"
1417 "github.com/eljojo/rememory/internal/html"
@@ -213,10 +216,21 @@ func loadShares(p *project.Project) ([]*core.Share, error) {
213216 return shares , nil
214217}
215218
216- // sanitizeName converts a name to a filesystem-safe lowercase string.
219+ // sanitizeName converts a name to a filesystem-safe lowercase ASCII string.
220+ // It transliterates accented/diacritic characters to their ASCII base form
221+ // (e.g. "José" → "jose", "Ñoño" → "nono") so that filenames are always valid.
217222func sanitizeName (name string ) string {
223+ // Decompose to NFD: splits characters like "é" into "e" + combining accent.
224+ // Then drop combining marks to keep only the base letter.
225+ var stripped []rune
226+ for _ , r := range norm .NFD .String (name ) {
227+ if ! unicode .Is (unicode .Mn , r ) { // Mn = Mark, Nonspacing (combining diacritics)
228+ stripped = append (stripped , r )
229+ }
230+ }
231+
218232 result := ""
219- for _ , r := range name {
233+ for _ , r := range stripped {
220234 if (r >= 'a' && r <= 'z' ) || (r >= 'A' && r <= 'Z' ) || (r >= '0' && r <= '9' ) {
221235 result += string (r )
222236 } else if r == ' ' || r == '-' || r == '_' {
Original file line number Diff line number Diff line change @@ -11,6 +11,9 @@ import (
1111 "fmt"
1212 "syscall/js"
1313 "time"
14+ "unicode"
15+
16+ "golang.org/x/text/unicode/norm"
1417
1518 "github.com/eljojo/rememory/internal/bundle"
1619 "github.com/eljojo/rememory/internal/core"
@@ -412,10 +415,21 @@ func trimLeadingSlashes(s string) string {
412415 return s
413416}
414417
415- // sanitizeName converts a name to a filesystem-safe lowercase string.
418+ // sanitizeName converts a name to a filesystem-safe lowercase ASCII string.
419+ // It transliterates accented/diacritic characters to their ASCII base form
420+ // (e.g. "José" → "jose", "Ñoño" → "nono") so that filenames are always valid.
416421func sanitizeName (name string ) string {
422+ // Decompose to NFD: splits characters like "é" into "e" + combining accent.
423+ // Then drop combining marks to keep only the base letter.
424+ var stripped []rune
425+ for _ , r := range norm .NFD .String (name ) {
426+ if ! unicode .Is (unicode .Mn , r ) { // Mn = Mark, Nonspacing (combining diacritics)
427+ stripped = append (stripped , r )
428+ }
429+ }
430+
417431 result := ""
418- for _ , r := range name {
432+ for _ , r := range stripped {
419433 if (r >= 'a' && r <= 'z' ) || (r >= 'A' && r <= 'Z' ) || (r >= '0' && r <= '9' ) {
420434 result += string (r )
421435 } else if r == ' ' || r == '-' || r == '_' {
You can’t perform that action at this time.
0 commit comments