From 7310664f7dbf7dd75d776136e28dfb50fcc867fe Mon Sep 17 00:00:00 2001 From: npmrun Date: Wed, 17 Aug 2022 02:22:42 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=92=E5=BA=8F=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/components/tree/better-directory-sort.ts | 92 +++++++++++++++++++++++ packages/components/tree/node.vue | 25 ++++-- packages/components/tree/tree.vue | 21 +++++- packages/components/tree/util.ts | 6 ++ packages/playground/src/dev/tree.vue | 10 +-- 5 files changed, 142 insertions(+), 12 deletions(-) create mode 100644 packages/components/tree/better-directory-sort.ts diff --git a/packages/components/tree/better-directory-sort.ts b/packages/components/tree/better-directory-sort.ts new file mode 100644 index 0000000..5063858 --- /dev/null +++ b/packages/components/tree/better-directory-sort.ts @@ -0,0 +1,92 @@ +function defaultComparator(a, b) { + return a.localeCompare(b, undefined, { + numeric: true, + sensitivity: "base", + }); +} + +function compareSafe(a, b, comparator) { + if (a == null && b == null) return 0; + if (a != null && b == null) return 1; + if (b != null && a == null) return -1; + return comparator(a, b); +} + +type Comparator = (a: T, b: T) => number; +type Entity = { + name: string; + isDirectory: boolean; +}; +type Opts = { + comparator?: Comparator; + kinds?: boolean; +}; + +function createBetterDirectorySort(opts: Opts = {}): Comparator { + let comparator = opts.comparator || defaultComparator; + let kinds = opts.kinds || false; + + return function betterDirectorySort(a, b) { + // directories should be placed before files + if (a.isDirectory && !b.isDirectory) return -1; + if (b.isDirectory && !a.isDirectory) return 1; + + // dotsfiles should be placed before non-dotfiles + let aDot = a.name[0] === "."; + let bDot = b.name[0] === "."; + if (aDot && !bDot) return -1; + if (bDot && !aDot) return 1; + + // names will be sorted in period-delimitted parts + let aParts = a.name.split("."); + let bParts = b.name.split("."); + + // the first part of the name is the most important part + let aName = aParts.shift(); + let bName = bParts.shift(); + + // final extension is only used when all else is the same + let aExt = aParts.pop(); + let bExt = bParts.pop(); + + let comparedName = compareSafe(aName, bName, comparator); + if (comparedName !== 0) return comparedName; + + // "kind" extension is used above other parts + if (kinds) { + let aKind = aParts.pop(); + let bKind = bParts.pop(); + + let comparedKind = compareSafe(aKind, bKind, comparator); + if (comparedKind !== 0) return comparedKind; + } + + // loop with an decrementing index + let i = 0; + while (true) { + let aPart = aParts[i]; + let bPart = bParts[i]; + + // if there's no more parts on either name, break + if (aPart == null && bPart == null) break; + + // compare the current part, if its the same, continue comparing parts + let comparedPart = compareSafe(aPart, bPart, comparator); + if (comparedPart !== 0) return comparedPart; + + i++; + } + + // compare the last extension as a final tie-breaker + return compareSafe(aExt, bExt, comparator); + }; +} + +const betterDirectorySort = createBetterDirectorySort(); + +// @ts-ignore +betterDirectorySort.custom = createBetterDirectorySort; +// @ts-ignore +betterDirectorySort.defaultComparator = defaultComparator; + +export { betterDirectorySort }; diff --git a/packages/components/tree/node.vue b/packages/components/tree/node.vue index ec3579b..da6579b 100644 --- a/packages/components/tree/node.vue +++ b/packages/components/tree/node.vue @@ -33,7 +33,7 @@ ]">
-