Skip to content

Commit e076650

Browse files
committed
plugin: add support for alphabetical sorting
1 parent e42c302 commit e076650

File tree

5 files changed

+110
-7
lines changed

5 files changed

+110
-7
lines changed

plugin/src/data/transformations/sorting.test.ts

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ function makeTask(id: string, opts?: Partial<Task>): Task {
99
id,
1010
createdAt: opts?.createdAt ?? "1970-01-01",
1111
parentId: opts?.parentId,
12-
content: "",
12+
content: opts?.content ?? "",
1313
description: "",
1414
labels: [],
1515
priority: opts?.priority ?? 1,
@@ -340,6 +340,96 @@ describe("sortTasks", () => {
340340
}),
341341
],
342342
},
343+
{
344+
description: "can sort alphabetically (ascending)",
345+
input: [
346+
makeTask("a", { content: "zebra" }),
347+
makeTask("b", { content: "apple" }),
348+
makeTask("c", { content: "Banana" }),
349+
makeTask("d", { content: "cherry" }),
350+
],
351+
sortingOpts: [SortingVariant.Alphabetical],
352+
expectedOutput: [
353+
makeTask("b", { content: "apple" }),
354+
makeTask("c", { content: "Banana" }),
355+
makeTask("d", { content: "cherry" }),
356+
makeTask("a", { content: "zebra" }),
357+
],
358+
},
359+
{
360+
description: "can sort alphabetically descending",
361+
input: [
362+
makeTask("a", { content: "apple" }),
363+
makeTask("b", { content: "Banana" }),
364+
makeTask("c", { content: "zebra" }),
365+
],
366+
sortingOpts: [SortingVariant.AlphabeticalDescending],
367+
expectedOutput: [
368+
makeTask("c", { content: "zebra" }),
369+
makeTask("b", { content: "Banana" }),
370+
makeTask("a", { content: "apple" }),
371+
],
372+
},
373+
{
374+
description: "alphabetical sort is case-insensitive",
375+
input: [
376+
makeTask("a", { content: "APPLE" }),
377+
makeTask("b", { content: "banana" }),
378+
makeTask("c", { content: "Apple" }),
379+
makeTask("d", { content: "BANANA" }),
380+
],
381+
sortingOpts: [SortingVariant.Alphabetical],
382+
expectedOutput: [
383+
makeTask("a", { content: "APPLE" }),
384+
makeTask("c", { content: "Apple" }),
385+
makeTask("b", { content: "banana" }),
386+
makeTask("d", { content: "BANANA" }),
387+
],
388+
},
389+
{
390+
description: "alphabetical sort handles special characters",
391+
input: [
392+
makeTask("a", { content: "2. Second task" }),
393+
makeTask("b", { content: "1. First task" }),
394+
makeTask("c", { content: "@mention task" }),
395+
makeTask("d", { content: "#hashtag task" }),
396+
],
397+
sortingOpts: [SortingVariant.Alphabetical],
398+
expectedOutput: [
399+
makeTask("c", { content: "@mention task" }),
400+
makeTask("d", { content: "#hashtag task" }),
401+
makeTask("b", { content: "1. First task" }),
402+
makeTask("a", { content: "2. Second task" }),
403+
],
404+
},
405+
{
406+
description: "alphabetical sort handles empty strings",
407+
input: [
408+
makeTask("a", { content: "" }),
409+
makeTask("b", { content: "apple" }),
410+
makeTask("c", { content: "" }),
411+
],
412+
sortingOpts: [SortingVariant.Alphabetical],
413+
expectedOutput: [
414+
makeTask("a", { content: "" }),
415+
makeTask("c", { content: "" }),
416+
makeTask("b", { content: "apple" }),
417+
],
418+
},
419+
{
420+
description: "can combine alphabetical sort with priority sorting",
421+
input: [
422+
makeTask("a", { content: "Task B", priority: 2 }),
423+
makeTask("b", { content: "Task A", priority: 2 }),
424+
makeTask("c", { content: "Task C", priority: 3 }),
425+
],
426+
sortingOpts: [SortingVariant.Priority, SortingVariant.Alphabetical],
427+
expectedOutput: [
428+
makeTask("c", { content: "Task C", priority: 3 }),
429+
makeTask("b", { content: "Task A", priority: 2 }),
430+
makeTask("a", { content: "Task B", priority: 2 }),
431+
],
432+
},
343433
];
344434

345435
for (const tc of testcases) {

plugin/src/data/transformations/sorting.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ function compareTask<T extends Task>(self: T, other: T, sorting: SortingVariant)
3939
return compareTaskDateAdded(self, other);
4040
case SortingVariant.DateAddedDescending:
4141
return -compareTaskDateAdded(self, other);
42+
case SortingVariant.Alphabetical:
43+
return compareTaskAlphabetical(self, other);
44+
case SortingVariant.AlphabeticalDescending:
45+
return -compareTaskAlphabetical(self, other);
4246
default:
4347
throw new Error(`Unexpected sorting type: '${sorting}'`);
4448
}
@@ -94,6 +98,10 @@ function compareTaskDateAdded<T extends Task>(self: T, other: T): number {
9498
return selfDate.compare(otherDate) < 0 ? -1 : 1;
9599
}
96100

101+
function compareTaskAlphabetical<T extends Task>(self: T, other: T): number {
102+
return self.content.localeCompare(other.content, undefined, { sensitivity: "base" });
103+
}
104+
97105
function isSameDay(a: Date, b: Date): boolean {
98106
return (
99107
a.getFullYear() === b.getFullYear() &&

plugin/src/query/__snapshots__/parser.test.ts.snap

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
exports[`parseQuery - error message snapshots > array with mixed valid and invalid enum values 1`] = `
44
[Error: Field 'sorting' elements have the following issues:
5-
Item 'sorting[1]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"]
5+
Item 'sorting[1]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"|"alphabetical"|"alphabeticalAscending"|"alphabeticalDescending"]
66
`;
77

88
exports[`parseQuery - error message snapshots > autorefresh must be a number 1`] = `
@@ -87,9 +87,9 @@ Field 'show' elements have the following issues:
8787

8888
exports[`parseQuery - error message snapshots > sorting array must contain strings 1`] = `
8989
[Error: Field 'sorting' elements have the following issues:
90-
Item 'sorting[0]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"
91-
Item 'sorting[1]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"
92-
Item 'sorting[2]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"]
90+
Item 'sorting[0]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"|"alphabetical"|"alphabeticalAscending"|"alphabeticalDescending"
91+
Item 'sorting[1]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"|"alphabetical"|"alphabeticalAscending"|"alphabeticalDescending"
92+
Item 'sorting[2]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"|"alphabetical"|"alphabeticalAscending"|"alphabeticalDescending"]
9393
`;
9494

9595
exports[`parseQuery - error message snapshots > sorting must be an array 1`] = `
@@ -99,6 +99,6 @@ exports[`parseQuery - error message snapshots > sorting must be an array 1`] = `
9999

100100
exports[`parseQuery - error message snapshots > sorting must have valid enum values 1`] = `
101101
[Error: Field 'sorting' elements have the following issues:
102-
Item 'sorting[0]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"
103-
Item 'sorting[1]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"]
102+
Item 'sorting[0]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"|"alphabetical"|"alphabeticalAscending"|"alphabeticalDescending"
103+
Item 'sorting[1]': Invalid option: expected one of "priority"|"priorityAscending"|"priorityDescending"|"date"|"dateAscending"|"dateDescending"|"order"|"dateAdded"|"dateAddedAscending"|"dateAddedDescending"|"alphabetical"|"alphabeticalAscending"|"alphabeticalDescending"]
104104
`;

plugin/src/query/parser.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ const sortingSchema = lookupToEnum({
9595
dateAdded: SortingVariant.DateAdded,
9696
dateAddedAscending: SortingVariant.DateAdded,
9797
dateAddedDescending: SortingVariant.DateAddedDescending,
98+
alphabetical: SortingVariant.Alphabetical,
99+
alphabeticalAscending: SortingVariant.Alphabetical,
100+
alphabeticalDescending: SortingVariant.AlphabeticalDescending,
98101
});
99102

100103
const showSchema = lookupToEnum({

plugin/src/query/query.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ export enum SortingVariant {
66
Order = 4,
77
DateAdded = 5,
88
DateAddedDescending = 6,
9+
Alphabetical = 7,
10+
AlphabeticalDescending = 8,
911
}
1012

1113
export enum ShowMetadataVariant {

0 commit comments

Comments
 (0)