diff --git a/blocksuite/affine/data-view/src/core/sort/eval.ts b/blocksuite/affine/data-view/src/core/sort/eval.ts index 71507b67980d8..d3e277b74f21a 100644 --- a/blocksuite/affine/data-view/src/core/sort/eval.ts +++ b/blocksuite/affine/data-view/src/core/sort/eval.ts @@ -48,32 +48,41 @@ const compareList = ( return 0; }; const compareString = (a: unknown, b: unknown): CompareType => { - if (typeof a != 'string' || a === '') { - return Compare.GT; + const strA = String(a ?? ''); + const strB = String(b ?? ''); + + if (strA === '' && strB !== '') { + return Compare.GT; // Empty strings come last } - if (typeof b != 'string' || b === '') { - return Compare.LT; + if (strA !== '' && strB === '') { + return Compare.LT; // Empty strings come last + } + if (strA === '' && strB === '') { + return 0; // Both empty, equal } - const listA = a.split('.'); - const listB = b.split('.'); + + const listA = strA.split('.'); + const listB = strB.split('.'); return compareList(listA, listB, (a, b) => { - const lowA = a.toLowerCase(); - const lowB = b.toLowerCase(); + const lowA = String(a).toLowerCase(); // Ensure 'a' and 'b' from split are strings too + const lowB = String(b).toLowerCase(); + const numberA = Number.parseInt(lowA); const numberB = Number.parseInt(lowB); const aIsNaN = Number.isNaN(numberA); const bIsNaN = Number.isNaN(numberB); + if (aIsNaN && !bIsNaN) { - return 1; + return 1; // Non-numeric part comes after numeric part } if (!aIsNaN && bIsNaN) { - return -1; + return -1; // Numeric part comes before non-numeric part } if (!aIsNaN && !bIsNaN && numberA !== numberB) { - return numberA - numberB; + return numberA - numberB; // Numeric comparison for numeric parts } - return lowA.localeCompare(lowB); + return lowA.localeCompare(lowB); // Lexicographical comparison for string parts }); }; const compareNumber = (a: unknown, b: unknown) => {