cross-path-sort
Cross-platform non-destructive file path sorting function.
Pass in an array of path strings or objects with a property whose value is path string. Get a new array with the same elements, sorted in a more intuitive way than with a simple sort:
- You can use shallowFirst/deepFirst options to separate the content of a directory from the content of its subdirectories.
simple sort vs this function with the shallowFirst option
one.js one.js
test/one_spec.js two.js
test/two_spec.js test/one_spec.js
two.js test/two_spec.js
- Different types of paths (relative, absolute, home, UNC, namespaced...) in the same array are always separated. You can change the default order of types.
simple sort vs this function on Windows
api.js api.js
C:\util\hash.js engine.js
engine.js C:\util\hash.js
The sort function:
- Works well with all kinds of paths on all platforms on which Node.js can be installed.
- Parses and sorts paths based on the platform on which it is running. See the Platforms section below for details.
- Normalizes path strings, but it always returns same strings/objects from the original array.
- Does not access the file system, it just works with the strings.
- By design, does not throw any exceptions related to the content of the paths array.
Installation and Usage
$ npm install cross-path-sort
This particular example will produce the same results on all platforms since
the forward slash /
is a valid separator on both Windows and POSIX (Linux, Unix, macOS...) systems:
const crossPathSort = ; const paths = 'one.js' 'test/one_spec.js' '/mylibs/hash.js' 'two.js' '/mylibs/encode/url.js' '/mylibs/assign.js' 'test/shared/init.js' 'test/two_spec.js' 'config/env.js'; const sortedPaths1 = crossPathSort;/* [ 'one.js', 'two.js', 'config/env.js', 'test/one_spec.js', 'test/two_spec.js', 'test/shared/init.js', '/mylibs/assign.js', '/mylibs/hash.js', '/mylibs/encode/url.js' ]*/ const sortedPaths2 = crossPathSort;/* [ 'config/env.js', 'test/shared/init.js', 'test/one_spec.js', 'test/two_spec.js', 'one.js', 'two.js', '/mylibs/encode/url.js', '/mylibs/assign.js', '/mylibs/hash.js' ]*/ // if you just want to separate path typesconst sortedPaths3 = crossPathSort;/* [ 'config/env.js', 'one.js', 'test/one_spec.js', 'test/shared/init.js', 'test/two_spec.js', 'two.js', '/mylibs/assign.js', '/mylibs/encode/url.js', '/mylibs/hash.js' ]*/
Had we used the backslash \
instead, results would be different on different platforms.
Platforms
The cross-platform sorting function assumes that the paths it works on are related to the operating system on which it is running. In other words, it assumes that the paths are either locally generated by your application or specified by its user.
The paths are normalized, parsed and sorted accordingly.
This module exposes three functions:
sort()
is the cross-platform sorting function, which you should use.posix.sort()
is POSIX-specific sorting function.windows.sort()
is Windows-specific sorting function.
Depending on the local platform, sort()
works like posix.sort()
or windows.sort()
.
You should always use just sort()
unless you have a specific application that doesn't work with local paths.
const crossPathSort = ; // escaped backslashconst paths = 'b\\a.js' 'c.js' 'a.js'; // on windows: b\a.js = file a.js in subdirectory bconst sortedOnWindows = crossPathSortwindows;/* [ 'a.js', 'c.js', 'b\\a.js' ]*/ // on posix: b\a.js = file b\a.jsconst sortedOnPosix = crossPathSortposix;/* [ 'a.js', 'b\\a.js', 'c.js' ]*/ const sortedLocally = crossPathSort;/* same as sortedOnWindows or sortedOnPosix, depending on your platform*/
All three functions have the same signature.
sort(paths, options)
parameters
paths
is an array of path strings or objects, see the paths and pathKey sections.
options
is an options object. All options are optional, and the whole object is optional.
returns
The function returns a new, sorted array with the exact same elements from the paths
array.
exceptions
Only if you specify invalid options. See the options below for details.
example
All options with their default values:
const sortedPaths = crossPathSort;
paths
Array of strings or objects, or even a mixed array of strings and objects.
By design, this array can contain anything:
string
elements andobject
elements whoseobject[pathKey]
isstring
will be treated equally and sorted.- All other elements will be treated as 'unreadable' and come after the sorted elements.
- Holes will be preserved and come at the very end of the resulting array.
If paths
is not an array, sort()
will simply return the same value.
pathKey
If you want to sort an array of your custom objects that contain path strings, use the pathKey
option
to specify the key of a property whose value represents the path string.
If specified, pathKey
should be a string
.
Path string of an object
element from the paths
array will be read from object[pathKey]
.
Notes:
- If your array has a mixed content,
pathKey
will be used only forobject
elements and ignored forstring
elements (string
element itself represents a path). - If
object[pathKey]
is not astring
, thatobject
element will be treated as 'unreadable'. - If you don't specify
pathKey
, allobject
elements will be treated as 'unreadable'.
Example:
const crossPathSort = ; const obj1 = file: 'c.js' ;const obj2 = file: 'b/a.js' ;const obj3 = {};const obj4 = file: 'a.js';const paths = obj1 obj2 obj3 obj4; const sortedPaths = crossPathSort;/* [obj4, obj1, obj2, obj3]*/
If your array contains just string
elements, you can leave this value undefined
.
sort()
will throw an exception if the pathKey
argument itself is not a string
or undefined
.
sort()
will NOT throw an exception if object[pathKey]
is not a string
.
shallowFirst & deepFirst
Default values are false
. Only one can be set to true
.
Sort has three modes:
- If
shallowFirst
istrue
, content of a directory will come before the content of its subdirectories. - If
deepFirst
istrue
, content of a directory will come after the content of its subdirectories. - If both values are
false
, file names will be compared with subdirectory names.
See the example in the Installation and Usage section above.
sort()
will throw an exception if both shallowFirst
and deepFirst
have a truthy value.
homePathsSupported
Default value is false
and paths starting with ~
are treated as relative paths, as the tilde is
a valid character for file names and directory names on all systems.
This is in line with how Node's modules such as fs
or path
treat these paths.
If your application explicitly supports shell-specific paths like ~/
or ~user/
, and you want
the paths starting with ~
to appear in a different partition of the resulting array as home paths, set
this value to true
.
Regarding the next section:
- If
homePathsSupported
isfalse
, paths starting with~
will be'rel'
paths. There will be nohome
paths. - If
homePathsSupported
istrue
, paths starting with~
will be'home'
paths.
posixOrder & windowsOrder
These options specify the order of different path types in the resulting array.
sort()
uses posixOrder
on POSIX platforms, windowsOrder
on Windows platforms.
POSIX path types
'rel'
are relative paths, such asa.js
andb/a.js
.'home'
are home paths, see the previous section.'abs'
are absolute paths, such as/a.js
and/b/a.js
.
posixOrder
default value is: ['rel', 'home', 'abs']
Windows path types
'rel'
are relative paths, such asa.js
andb\a.js
'home'
are home paths, see the previous section.'abs'
are absolute paths, such as\a.js
and\b\a.js
.'drel'
are relative paths with a specified drive, such asC:a.js
andC:b\a.js
.'dabs'
are absolute paths with a specified drive, such asC:\a.js
andC:\b\a.js
.'unc'
are UNC paths, such as\\server\share\a.js
and\\server\share\b\a.js
.'nms'
are namespaced paths - paths starting with\\?\
or\\.\
.
windowsOrder
default value is: ['rel', 'home', 'abs', 'drel', 'dabs', 'unc', 'nms']
Since the forward slash /
is a valid separator on Windows, paths like /a.js
on Windows are also 'abs'
type paths,
paths like C:/a.js
on Windows are also 'dabs'
type paths etc.
Example:
const crossPathSort = ; const paths = 'one.js' 'test/one_spec.js' '/mylibs/hash.js' 'two.js' '/mylibs/encode/url.js' '/mylibs/assign.js' 'test/shared/init.js' 'test/two_spec.js' 'config/env.js'; // position of the 'home' type is irrelevant if homePathsSupported is not trueconst sortedPaths1 = crossPathSort;/* [ '/mylibs/assign.js', '/mylibs/hash.js', '/mylibs/encode/url.js', 'one.js', 'two.js', 'config/env.js', 'test/one_spec.js', 'test/two_spec.js', 'test/shared/init.js' ]*/
sort()
will throw an exception if the posixOrder
argument is not an array
or undefined
.
An array
must be a permutation of the default array. The same applies to the windowsOrder
argument.
segmentCompareFn
Function used to compare path segments such as file names, directory names, drive letters etc.
Default function is: (a, b) => a.localeCompare(b)
If you don't specify this option, the default function will be used.
Your custom function should work like a function you would use with Array.prototype.sort()
.
The function will always get two string
values, and should return a number that is < 0
, 0
or > 0
.
sort()
will throw an exception if segmentCompareFn
is not a function
or undefined
.
Also, sort()
does not catch exceptions thrown by your function.
If your function throws an exception, the whole sort()
will throw that exception.