From abe569001871bd1482b115904a304f5a9178a6be Mon Sep 17 00:00:00 2001 From: Deluan <deluan@navidrome.org> Date: Wed, 5 Jun 2024 22:09:27 -0400 Subject: [PATCH] Refactor string utilities into its own package `str` --- core/artwork/reader_artist.go | 4 +- core/external_metadata.go | 24 ++----- ...01213124814_add_all_artist_ids_to_album.go | 4 +- ...1026191915_unescape_lyrics_and_comments.go | 6 +- model/lyrics.go | 8 +-- model/mediafile.go | 4 +- persistence/artist_repository.go | 3 +- persistence/sql_search.go | 6 +- scanner/mapping.go | 12 ++-- server/serve_index.go | 8 +-- utils/sanitize_strings_test.go | 32 --------- utils/{ => str}/sanitize_strings.go | 12 +++- utils/str/sanitize_strings_test.go | 66 +++++++++++++++++++ utils/{strings.go => str/str.go} | 25 +++---- utils/str/str_suite_test.go | 13 ++++ utils/{strings_test.go => str/str_test.go} | 56 ++++++---------- 16 files changed, 158 insertions(+), 125 deletions(-) delete mode 100644 utils/sanitize_strings_test.go rename utils/{ => str}/sanitize_strings.go (72%) create mode 100644 utils/str/sanitize_strings_test.go rename utils/{strings.go => str/str.go} (61%) create mode 100644 utils/str/str_suite_test.go rename utils/{strings_test.go => str/str_test.go} (89%) diff --git a/core/artwork/reader_artist.go b/core/artwork/reader_artist.go index b25858f0c..3e13da9b4 100644 --- a/core/artwork/reader_artist.go +++ b/core/artwork/reader_artist.go @@ -17,7 +17,7 @@ import ( "github.com/navidrome/navidrome/core" "github.com/navidrome/navidrome/log" "github.com/navidrome/navidrome/model" - "github.com/navidrome/navidrome/utils" + "github.com/navidrome/navidrome/utils/str" ) type artistReader struct { @@ -56,7 +56,7 @@ func newArtistReader(ctx context.Context, artwork *artwork, artID model.ArtworkI } } a.files = strings.Join(files, consts.Zwsp) - a.artistFolder = utils.LongestCommonPrefix(paths) + a.artistFolder = str.LongestCommonPrefix(paths) if !strings.HasSuffix(a.artistFolder, string(filepath.Separator)) { a.artistFolder, _ = filepath.Split(a.artistFolder) } diff --git a/core/external_metadata.go b/core/external_metadata.go index c95f044c9..f0eec6519 100644 --- a/core/external_metadata.go +++ b/core/external_metadata.go @@ -19,6 +19,7 @@ import ( "github.com/navidrome/navidrome/utils" . "github.com/navidrome/navidrome/utils/gg" "github.com/navidrome/navidrome/utils/random" + "github.com/navidrome/navidrome/utils/str" "golang.org/x/sync/errgroup" ) @@ -74,7 +75,7 @@ func (e *externalMetadata) getAlbum(ctx context.Context, id string) (*auxAlbum, switch v := entity.(type) { case *model.Album: album.Album = *v - album.Name = clearName(v.Name) + album.Name = str.Clear(v.Name) case *model.MediaFile: return e.getAlbum(ctx, v.AlbumID) default: @@ -164,7 +165,7 @@ func (e *externalMetadata) getArtist(ctx context.Context, id string) (*auxArtist switch v := entity.(type) { case *model.Artist: artist.Artist = *v - artist.Name = clearName(v.Name) + artist.Name = str.Clear(v.Name) case *model.MediaFile: return e.getArtist(ctx, v.ArtistID) case *model.Album: @@ -175,17 +176,6 @@ func (e *externalMetadata) getArtist(ctx context.Context, id string) (*auxArtist return &artist, nil } -// Replace some Unicode chars with their equivalent ASCII -func clearName(name string) string { - name = strings.ReplaceAll(name, "–", "-") - name = strings.ReplaceAll(name, "‐", "-") - name = strings.ReplaceAll(name, "“", `"`) - name = strings.ReplaceAll(name, "”", `"`) - name = strings.ReplaceAll(name, "‘", `'`) - name = strings.ReplaceAll(name, "’", `'`) - return name -} - func (e *externalMetadata) UpdateArtistInfo(ctx context.Context, id string, similarCount int, includeNotPresent bool) (*model.Artist, error) { artist, err := e.refreshArtistInfo(ctx, id) if err != nil { @@ -414,7 +404,7 @@ func (e *externalMetadata) findMatchingTrack(ctx context.Context, mbid string, a squirrel.Eq{"artist_id": artistID}, squirrel.Eq{"album_artist_id": artistID}, }, - squirrel.Like{"order_title": utils.SanitizeFieldForSorting(title)}, + squirrel.Like{"order_title": str.SanitizeFieldForSorting(title)}, }, Sort: "starred desc, rating desc, year asc, compilation asc ", Max: 1, @@ -434,11 +424,11 @@ func (e *externalMetadata) callGetURL(ctx context.Context, agent agents.ArtistUR } func (e *externalMetadata) callGetBiography(ctx context.Context, agent agents.ArtistBiographyRetriever, artist *auxArtist) { - bio, err := agent.GetArtistBiography(ctx, artist.ID, clearName(artist.Name), artist.MbzArtistID) + bio, err := agent.GetArtistBiography(ctx, artist.ID, str.Clear(artist.Name), artist.MbzArtistID) if err != nil { return } - bio = utils.SanitizeText(bio) + bio = str.SanitizeText(bio) bio = strings.ReplaceAll(bio, "\n", " ") artist.Biography = strings.ReplaceAll(bio, "<a ", "<a target='_blank' ") } @@ -514,7 +504,7 @@ func (e *externalMetadata) findArtistByName(ctx context.Context, artistName stri } artist := &auxArtist{ Artist: artists[0], - Name: clearName(artists[0].Name), + Name: str.Clear(artists[0].Name), } return artist, nil } diff --git a/db/migrations/20201213124814_add_all_artist_ids_to_album.go b/db/migrations/20201213124814_add_all_artist_ids_to_album.go index 8cdb79fe0..170497f5c 100644 --- a/db/migrations/20201213124814_add_all_artist_ids_to_album.go +++ b/db/migrations/20201213124814_add_all_artist_ids_to_album.go @@ -5,7 +5,7 @@ import ( "database/sql" "github.com/navidrome/navidrome/log" - "github.com/navidrome/navidrome/utils" + "github.com/navidrome/navidrome/utils/str" "github.com/pressly/goose/v3" ) @@ -50,7 +50,7 @@ select a.id, a.name, a.artist_id, a.album_artist_id, group_concat(mf.artist_id, if err != nil { return err } - all := utils.SanitizeStrings(artistId, albumArtistId, songArtistIds.String) + all := str.SanitizeStrings(artistId, albumArtistId, songArtistIds.String) _, err = stmt.Exec(all, id) if err != nil { log.Error("Error setting album's artist_ids", "album", name, "albumId", id, err) diff --git a/db/migrations/20211026191915_unescape_lyrics_and_comments.go b/db/migrations/20211026191915_unescape_lyrics_and_comments.go index ee010c93e..d4ba5e194 100644 --- a/db/migrations/20211026191915_unescape_lyrics_and_comments.go +++ b/db/migrations/20211026191915_unescape_lyrics_and_comments.go @@ -5,7 +5,7 @@ import ( "database/sql" "github.com/navidrome/navidrome/log" - "github.com/navidrome/navidrome/utils" + "github.com/navidrome/navidrome/utils/str" "github.com/pressly/goose/v3" ) @@ -33,8 +33,8 @@ func upUnescapeLyricsAndComments(_ context.Context, tx *sql.Tx) error { return err } - newComment := utils.SanitizeText(comment.String) - newLyrics := utils.SanitizeText(lyrics.String) + newComment := str.SanitizeText(comment.String) + newLyrics := str.SanitizeText(lyrics.String) _, err = stmt.Exec(newComment, newLyrics, id) if err != nil { log.Error("Error unescaping media_file's lyrics and comments", "title", title, "id", id, err) diff --git a/model/lyrics.go b/model/lyrics.go index e45f53d62..f7221f84f 100644 --- a/model/lyrics.go +++ b/model/lyrics.go @@ -8,7 +8,7 @@ import ( "strings" "github.com/navidrome/navidrome/log" - "github.com/navidrome/navidrome/utils" + "github.com/navidrome/navidrome/utils/str" ) type Line struct { @@ -36,7 +36,7 @@ var ( ) func ToLyrics(language, text string) (*Lyrics, error) { - text = utils.SanitizeText(text) + text = str.SanitizeText(text) lines := strings.Split(text, "\n") @@ -67,7 +67,7 @@ func ToLyrics(language, text string) (*Lyrics, error) { if idTag != nil { switch idTag[1] { case "ar": - artist = utils.SanitizeText(strings.TrimSpace(idTag[2])) + artist = str.SanitizeText(strings.TrimSpace(idTag[2])) case "offset": { off, err := strconv.ParseInt(strings.TrimSpace(idTag[2]), 10, 64) @@ -78,7 +78,7 @@ func ToLyrics(language, text string) (*Lyrics, error) { } } case "ti": - title = utils.SanitizeText(strings.TrimSpace(idTag[2])) + title = str.SanitizeText(strings.TrimSpace(idTag[2])) } continue diff --git a/model/mediafile.go b/model/mediafile.go index 935b73689..7d5a87d62 100644 --- a/model/mediafile.go +++ b/model/mediafile.go @@ -12,8 +12,8 @@ import ( "github.com/navidrome/navidrome/conf" "github.com/navidrome/navidrome/consts" - "github.com/navidrome/navidrome/utils" "github.com/navidrome/navidrome/utils/slice" + "github.com/navidrome/navidrome/utils/str" ) type MediaFile struct { @@ -187,7 +187,7 @@ func (mfs MediaFiles) ToAlbum() Album { a.Genre = slice.MostFrequent(a.Genres).Name slices.SortFunc(a.Genres, func(a, b Genre) int { return cmp.Compare(a.ID, b.ID) }) a.Genres = slices.Compact(a.Genres) - a.FullText = " " + utils.SanitizeStrings(fullText...) + a.FullText = " " + str.SanitizeStrings(fullText...) a = fixAlbumArtist(a, albumArtistIds) songArtistIds = append(songArtistIds, a.AlbumArtistID, a.ArtistID) slices.Sort(songArtistIds) diff --git a/persistence/artist_repository.go b/persistence/artist_repository.go index 74b44d2f5..945179085 100644 --- a/persistence/artist_repository.go +++ b/persistence/artist_repository.go @@ -14,6 +14,7 @@ import ( "github.com/navidrome/navidrome/log" "github.com/navidrome/navidrome/model" "github.com/navidrome/navidrome/utils" + "github.com/navidrome/navidrome/utils/str" "github.com/pocketbase/dbx" ) @@ -140,7 +141,7 @@ func (r *artistRepository) toModels(dba []dbArtist) model.Artists { } func (r *artistRepository) getIndexKey(a *model.Artist) string { - name := strings.ToLower(utils.NoArticle(a.Name)) + name := strings.ToLower(str.NoArticle(a.Name)) for k, v := range r.indexGroups { key := strings.ToLower(k) if strings.HasPrefix(name, key) { diff --git a/persistence/sql_search.go b/persistence/sql_search.go index 282455e84..98e7760ec 100644 --- a/persistence/sql_search.go +++ b/persistence/sql_search.go @@ -6,11 +6,11 @@ import ( . "github.com/Masterminds/squirrel" "github.com/navidrome/navidrome/conf" "github.com/navidrome/navidrome/model" - "github.com/navidrome/navidrome/utils" + "github.com/navidrome/navidrome/utils/str" ) func getFullText(text ...string) string { - fullText := utils.SanitizeStrings(text...) + fullText := str.SanitizeStrings(text...) return " " + fullText } @@ -39,7 +39,7 @@ func (r sqlRepository) doSearch(q string, offset, size int, results interface{}, } func fullTextExpr(value string) Sqlizer { - q := utils.SanitizeStrings(value) + q := str.SanitizeStrings(value) if q == "" { return nil } diff --git a/scanner/mapping.go b/scanner/mapping.go index a67823a9d..79195157d 100644 --- a/scanner/mapping.go +++ b/scanner/mapping.go @@ -11,7 +11,7 @@ import ( "github.com/navidrome/navidrome/consts" "github.com/navidrome/navidrome/model" "github.com/navidrome/navidrome/scanner/metadata" - "github.com/navidrome/navidrome/utils" + "github.com/navidrome/navidrome/utils/str" ) type MediaFileMapper struct { @@ -56,10 +56,10 @@ func (s MediaFileMapper) ToMediaFile(md metadata.Tags) model.MediaFile { mf.SortAlbumName = md.SortAlbum() mf.SortArtistName = md.SortArtist() mf.SortAlbumArtistName = md.SortAlbumArtist() - mf.OrderTitle = utils.SanitizeFieldForSorting(mf.Title) - mf.OrderAlbumName = utils.SanitizeFieldForSortingNoArticle(mf.Album) - mf.OrderArtistName = utils.SanitizeFieldForSortingNoArticle(mf.Artist) - mf.OrderAlbumArtistName = utils.SanitizeFieldForSortingNoArticle(mf.AlbumArtist) + mf.OrderTitle = str.SanitizeFieldForSorting(mf.Title) + mf.OrderAlbumName = str.SanitizeFieldForSortingNoArticle(mf.Album) + mf.OrderArtistName = str.SanitizeFieldForSortingNoArticle(mf.Artist) + mf.OrderAlbumArtistName = str.SanitizeFieldForSortingNoArticle(mf.AlbumArtist) mf.CatalogNum = md.CatalogNum() mf.MbzRecordingID = md.MbzRecordingID() mf.MbzReleaseTrackID = md.MbzReleaseTrackID() @@ -72,7 +72,7 @@ func (s MediaFileMapper) ToMediaFile(md metadata.Tags) model.MediaFile { mf.RgAlbumPeak = md.RGAlbumPeak() mf.RgTrackGain = md.RGTrackGain() mf.RgTrackPeak = md.RGTrackPeak() - mf.Comment = utils.SanitizeText(md.Comment()) + mf.Comment = str.SanitizeText(md.Comment()) mf.Lyrics = md.Lyrics() mf.Bpm = md.Bpm() mf.CreatedAt = md.BirthTime() diff --git a/server/serve_index.go b/server/serve_index.go index 11b679b80..4d48f5424 100644 --- a/server/serve_index.go +++ b/server/serve_index.go @@ -15,8 +15,8 @@ import ( "github.com/navidrome/navidrome/consts" "github.com/navidrome/navidrome/log" "github.com/navidrome/navidrome/model" - "github.com/navidrome/navidrome/utils" "github.com/navidrome/navidrome/utils/slice" + "github.com/navidrome/navidrome/utils/str" ) func Index(ds model.DataStore, fs fs.FS) http.HandlerFunc { @@ -42,9 +42,9 @@ func serveIndex(ds model.DataStore, fs fs.FS, shareInfo *model.Share) http.Handl "version": consts.Version, "firstTime": firstTime, "variousArtistsId": consts.VariousArtistsID, - "baseURL": utils.SanitizeText(strings.TrimSuffix(conf.Server.BasePath, "/")), - "loginBackgroundURL": utils.SanitizeText(conf.Server.UILoginBackgroundURL), - "welcomeMessage": utils.SanitizeText(conf.Server.UIWelcomeMessage), + "baseURL": str.SanitizeText(strings.TrimSuffix(conf.Server.BasePath, "/")), + "loginBackgroundURL": str.SanitizeText(conf.Server.UILoginBackgroundURL), + "welcomeMessage": str.SanitizeText(conf.Server.UIWelcomeMessage), "maxSidebarPlaylists": conf.Server.MaxSidebarPlaylists, "enableTranscodingConfig": conf.Server.EnableTranscodingConfig, "enableDownloads": conf.Server.EnableDownloads, diff --git a/utils/sanitize_strings_test.go b/utils/sanitize_strings_test.go deleted file mode 100644 index 393111fc5..000000000 --- a/utils/sanitize_strings_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package utils - -import ( - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -var _ = Describe("SanitizeStrings", func() { - It("returns all lowercase chars", func() { - Expect(SanitizeStrings("Some Text")).To(Equal("some text")) - }) - - It("removes accents", func() { - Expect(SanitizeStrings("Quintão")).To(Equal("quintao")) - }) - - It("remove extra spaces", func() { - Expect(SanitizeStrings(" some text ")).To(Equal("some text")) - }) - - It("remove duplicated words", func() { - Expect(SanitizeStrings("legião urbana urbana legiÃo")).To(Equal("legiao urbana")) - }) - - It("remove symbols", func() { - Expect(SanitizeStrings("Tom’s Diner ' “40” ‘A’")).To(Equal("40 a diner toms")) - }) - - It("remove opening brackets", func() { - Expect(SanitizeStrings("[Five Years]")).To(Equal("five years")) - }) -}) diff --git a/utils/sanitize_strings.go b/utils/str/sanitize_strings.go similarity index 72% rename from utils/sanitize_strings.go rename to utils/str/sanitize_strings.go index a8d9b576a..9a72206e0 100644 --- a/utils/sanitize_strings.go +++ b/utils/str/sanitize_strings.go @@ -1,4 +1,4 @@ -package utils +package str import ( "html" @@ -38,3 +38,13 @@ func SanitizeText(text string) string { s := policy.Sanitize(text) return html.UnescapeString(s) } + +func SanitizeFieldForSorting(originalValue string) string { + v := strings.TrimSpace(sanitize.Accents(originalValue)) + return strings.ToLower(v) +} + +func SanitizeFieldForSortingNoArticle(originalValue string) string { + v := strings.TrimSpace(sanitize.Accents(originalValue)) + return strings.ToLower(NoArticle(v)) +} diff --git a/utils/str/sanitize_strings_test.go b/utils/str/sanitize_strings_test.go new file mode 100644 index 000000000..e623dd5ed --- /dev/null +++ b/utils/str/sanitize_strings_test.go @@ -0,0 +1,66 @@ +package str_test + +import ( + "github.com/navidrome/navidrome/conf" + "github.com/navidrome/navidrome/utils/str" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = Describe("Sanitize Strings", func() { + Describe("SanitizeStrings", func() { + It("returns all lowercase chars", func() { + Expect(str.SanitizeStrings("Some Text")).To(Equal("some text")) + }) + + It("removes accents", func() { + Expect(str.SanitizeStrings("Quintão")).To(Equal("quintao")) + }) + + It("remove extra spaces", func() { + Expect(str.SanitizeStrings(" some text ")).To(Equal("some text")) + }) + + It("remove duplicated words", func() { + Expect(str.SanitizeStrings("legião urbana urbana legiÃo")).To(Equal("legiao urbana")) + }) + + It("remove symbols", func() { + Expect(str.SanitizeStrings("Tom’s Diner ' “40” ‘A’")).To(Equal("40 a diner toms")) + }) + + It("remove opening brackets", func() { + Expect(str.SanitizeStrings("[Five Years]")).To(Equal("five years")) + }) + }) + + Describe("SanitizeFieldForSorting", func() { + BeforeEach(func() { + conf.Server.IgnoredArticles = "The O" + }) + It("sanitize accents", func() { + Expect(str.SanitizeFieldForSorting("Céu")).To(Equal("ceu")) + }) + It("removes articles", func() { + Expect(str.SanitizeFieldForSorting("The Beatles")).To(Equal("the beatles")) + }) + It("removes accented articles", func() { + Expect(str.SanitizeFieldForSorting("Õ Blésq Blom")).To(Equal("o blesq blom")) + }) + }) + + Describe("SanitizeFieldForSortingNoArticle", func() { + BeforeEach(func() { + conf.Server.IgnoredArticles = "The O" + }) + It("sanitize accents", func() { + Expect(str.SanitizeFieldForSortingNoArticle("Céu")).To(Equal("ceu")) + }) + It("removes articles", func() { + Expect(str.SanitizeFieldForSortingNoArticle("The Beatles")).To(Equal("beatles")) + }) + It("removes accented articles", func() { + Expect(str.SanitizeFieldForSortingNoArticle("Õ Blésq Blom")).To(Equal("blesq blom")) + }) + }) +}) diff --git a/utils/strings.go b/utils/str/str.go similarity index 61% rename from utils/strings.go rename to utils/str/str.go index 42866a48c..b52a8cb53 100644 --- a/utils/strings.go +++ b/utils/str/str.go @@ -1,12 +1,23 @@ -package utils +package str import ( "strings" - "github.com/deluan/sanitize" "github.com/navidrome/navidrome/conf" ) +func Clear(name string) string { + r := strings.NewReplacer( + "–", "-", + "‐", "-", + "“", `"`, + "”", `"`, + "‘", `'`, + "’", `'`, + ) + return r.Replace(name) +} + func NoArticle(name string) string { articles := strings.Split(conf.Server.IgnoredArticles, " ") for _, a := range articles { @@ -33,13 +44,3 @@ func LongestCommonPrefix(list []string) string { } return list[0] } - -func SanitizeFieldForSorting(originalValue string) string { - v := strings.TrimSpace(sanitize.Accents(originalValue)) - return strings.ToLower(v) -} - -func SanitizeFieldForSortingNoArticle(originalValue string) string { - v := strings.TrimSpace(sanitize.Accents(originalValue)) - return strings.ToLower(NoArticle(v)) -} diff --git a/utils/str/str_suite_test.go b/utils/str/str_suite_test.go new file mode 100644 index 000000000..15cb12783 --- /dev/null +++ b/utils/str/str_suite_test.go @@ -0,0 +1,13 @@ +package str_test + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestStrClear(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Str Suite") +} diff --git a/utils/strings_test.go b/utils/str/str_test.go similarity index 89% rename from utils/strings_test.go rename to utils/str/str_test.go index 0d7b72e61..64df3493a 100644 --- a/utils/strings_test.go +++ b/utils/str/str_test.go @@ -1,11 +1,24 @@ -package utils +package str_test import ( "github.com/navidrome/navidrome/conf" + "github.com/navidrome/navidrome/utils/str" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) +var _ = Describe("Clean", func() { + DescribeTable("replaces some Unicode chars with their equivalent ASCII", + func(input, expected string) { + Expect(str.Clear(input)).To(Equal(expected)) + }, + Entry("k-os", "k–os", "k-os"), + Entry("k‐os", "k‐os", "k-os"), + Entry(`"Weird" Al Yankovic`, "“Weird” Al Yankovic", `"Weird" Al Yankovic`), + Entry("Single quotes", "‘Single’ quotes", "'Single' quotes"), + ) +}) + var _ = Describe("Strings", func() { Describe("NoArticle", func() { Context("Empty articles list", func() { @@ -13,10 +26,10 @@ var _ = Describe("Strings", func() { conf.Server.IgnoredArticles = "" }) It("returns empty if string is empty", func() { - Expect(NoArticle("")).To(BeEmpty()) + Expect(str.NoArticle("")).To(BeEmpty()) }) It("returns same string", func() { - Expect(NoArticle("The Beatles")).To(Equal("The Beatles")) + Expect(str.NoArticle("The Beatles")).To(Equal("The Beatles")) }) }) Context("Default articles", func() { @@ -24,49 +37,20 @@ var _ = Describe("Strings", func() { conf.Server.IgnoredArticles = "The El La Los Las Le Les Os As O A" }) It("returns empty if string is empty", func() { - Expect(NoArticle("")).To(BeEmpty()) + Expect(str.NoArticle("")).To(BeEmpty()) }) It("remove prefix article from string", func() { - Expect(NoArticle("Os Paralamas do Sucesso")).To(Equal("Paralamas do Sucesso")) + Expect(str.NoArticle("Os Paralamas do Sucesso")).To(Equal("Paralamas do Sucesso")) }) It("does not remove article if it is part of the first word", func() { - Expect(NoArticle("Thelonious Monk")).To(Equal("Thelonious Monk")) + Expect(str.NoArticle("Thelonious Monk")).To(Equal("Thelonious Monk")) }) }) }) - Describe("sanitizeFieldForSorting", func() { - BeforeEach(func() { - conf.Server.IgnoredArticles = "The O" - }) - It("sanitize accents", func() { - Expect(SanitizeFieldForSorting("Céu")).To(Equal("ceu")) - }) - It("removes articles", func() { - Expect(SanitizeFieldForSorting("The Beatles")).To(Equal("the beatles")) - }) - It("removes accented articles", func() { - Expect(SanitizeFieldForSorting("Õ Blésq Blom")).To(Equal("o blesq blom")) - }) - }) - Describe("SanitizeFieldForSortingNoArticle", func() { - BeforeEach(func() { - conf.Server.IgnoredArticles = "The O" - }) - It("sanitize accents", func() { - Expect(SanitizeFieldForSortingNoArticle("Céu")).To(Equal("ceu")) - }) - It("removes articles", func() { - Expect(SanitizeFieldForSortingNoArticle("The Beatles")).To(Equal("beatles")) - }) - It("removes accented articles", func() { - Expect(SanitizeFieldForSortingNoArticle("Õ Blésq Blom")).To(Equal("blesq blom")) - }) - }) - Describe("LongestCommonPrefix", func() { It("finds the longest common prefix", func() { - Expect(LongestCommonPrefix(testPaths)).To(Equal("/Music/iTunes 1/iTunes Media/Music/")) + Expect(str.LongestCommonPrefix(testPaths)).To(Equal("/Music/iTunes 1/iTunes Media/Music/")) }) })