fix: ignore emoji when sorting (#2687)
* fix: ignore emoji when sorting * fix: use correct flow types * fix: use emoji-regex
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
// @flow
|
// @flow
|
||||||
|
import emojiRegex from "emoji-regex";
|
||||||
import { deburr } from "lodash";
|
import { deburr } from "lodash";
|
||||||
import naturalSort from "natural-sort";
|
import naturalSort from "natural-sort";
|
||||||
|
|
||||||
@@ -9,20 +10,25 @@ type NaturalSortOptions = {
|
|||||||
|
|
||||||
const sorter = naturalSort();
|
const sorter = naturalSort();
|
||||||
|
|
||||||
|
const regex = emojiRegex();
|
||||||
|
const stripEmojis = (value: string) => value.replace(regex, "");
|
||||||
|
|
||||||
|
const cleanValue = (value: string) => stripEmojis(deburr(value));
|
||||||
|
|
||||||
function getSortByField<T: Object>(
|
function getSortByField<T: Object>(
|
||||||
item: T,
|
item: T,
|
||||||
keyOrCallback: string | ((T) => string)
|
keyOrCallback: string | ((obj: T) => string)
|
||||||
) {
|
) {
|
||||||
if (typeof keyOrCallback === "string") {
|
const field =
|
||||||
return deburr(item[keyOrCallback]);
|
typeof keyOrCallback === "string"
|
||||||
}
|
? item[keyOrCallback]
|
||||||
|
: keyOrCallback(item);
|
||||||
return keyOrCallback(item);
|
return cleanValue(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
function naturalSortBy<T>(
|
function naturalSortBy<T>(
|
||||||
items: T[],
|
items: T[],
|
||||||
key: string | ((T) => string),
|
key: string | ((obj: T) => string),
|
||||||
sortOptions?: NaturalSortOptions
|
sortOptions?: NaturalSortOptions
|
||||||
): T[] {
|
): T[] {
|
||||||
if (!items) return [];
|
if (!items) return [];
|
||||||
|
|||||||
61
shared/utils/naturalSort.test.js
Normal file
61
shared/utils/naturalSort.test.js
Normal file
@@ -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" },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user