From dc92e1ead4cb99d954307d1f20a76b679b18276e Mon Sep 17 00:00:00 2001 From: Gaston Flores Date: Sun, 24 Oct 2021 16:29:57 -0300 Subject: [PATCH] fix: ignore emoji when sorting (#2687) * fix: ignore emoji when sorting * fix: use correct flow types * fix: use emoji-regex --- shared/utils/naturalSort.js | 20 +++++++---- shared/utils/naturalSort.test.js | 61 ++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 7 deletions(-) create mode 100644 shared/utils/naturalSort.test.js diff --git a/shared/utils/naturalSort.js b/shared/utils/naturalSort.js index ba7a594ac..9f53e016d 100644 --- a/shared/utils/naturalSort.js +++ b/shared/utils/naturalSort.js @@ -1,4 +1,5 @@ // @flow +import emojiRegex from "emoji-regex"; import { deburr } from "lodash"; import naturalSort from "natural-sort"; @@ -9,20 +10,25 @@ type NaturalSortOptions = { const sorter = naturalSort(); +const regex = emojiRegex(); +const stripEmojis = (value: string) => value.replace(regex, ""); + +const cleanValue = (value: string) => stripEmojis(deburr(value)); + function getSortByField( item: T, - keyOrCallback: string | ((T) => string) + keyOrCallback: string | ((obj: T) => string) ) { - if (typeof keyOrCallback === "string") { - return deburr(item[keyOrCallback]); - } - - return keyOrCallback(item); + const field = + typeof keyOrCallback === "string" + ? item[keyOrCallback] + : keyOrCallback(item); + return cleanValue(field); } function naturalSortBy( items: T[], - key: string | ((T) => string), + key: string | ((obj: T) => string), sortOptions?: NaturalSortOptions ): T[] { if (!items) return []; diff --git a/shared/utils/naturalSort.test.js b/shared/utils/naturalSort.test.js new file mode 100644 index 000000000..c25d51173 --- /dev/null +++ b/shared/utils/naturalSort.test.js @@ -0,0 +1,61 @@ +// @flow +import naturalSort from "./naturalSort"; + +describe("#naturalSort", () => { + it("should sort a list of objects by the given key", () => { + const items = [{ name: "Joan" }, { name: "Pedro" }, { name: "Mark" }]; + expect(naturalSort(items, "name")).toEqual([ + { name: "Joan" }, + { name: "Mark" }, + { name: "Pedro" }, + ]); + }); + + it("should accept a function as the object key", () => { + const items = [{ name: "Joan" }, { name: "Pedro" }, { name: "Mark" }]; + expect(naturalSort(items, (item) => item.name)).toEqual([ + { name: "Joan" }, + { name: "Mark" }, + { name: "Pedro" }, + ]); + }); + + it("should accept natural-sort options", () => { + const items = [ + { name: "Joan" }, + { name: "joan" }, + { name: "Pedro" }, + { name: "Mark" }, + ]; + expect( + naturalSort(items, "name", { direction: "desc", caseSensitive: true }) + ).toEqual([ + { name: "joan" }, + { name: "Pedro" }, + { name: "Mark" }, + { name: "Joan" }, + ]); + }); + + it("should ignore non basic latin letters", () => { + const items = [{ name: "Abel" }, { name: "Martín" }, { name: "Ávila" }]; + expect(naturalSort(items, "name")).toEqual([ + { name: "Abel" }, + { name: "Ávila" }, + { name: "Martín" }, + ]); + }); + + it("should ignore emojis", () => { + const items = [ + { title: "🍔 Document 2" }, + { title: "🐻 Document 3" }, + { title: "🙂 Document 1" }, + ]; + expect(naturalSort(items, "title")).toEqual([ + { title: "🙂 Document 1" }, + { title: "🍔 Document 2" }, + { title: "🐻 Document 3" }, + ]); + }); +});