sort-paths.js
function sortPaths(items/* , [iteratee, ] dirSeparator */) {
    assert(arguments.length >= 2, 'too few arguments');
    assert(arguments.length <= 3, 'too many arguments');

    var iteratee, dirSeparator;

    if (arguments.length === 2) {
        iteratee = identity;
        dirSeparator = arguments[1];
    }
    else {
        iteratee = arguments[1];
        dirSeparator = arguments[2];
    }

    assert(isArray(items), 'items is not an array');
    assert(isFunction(iteratee), 'iteratee is not a function');
    assert(typeof dirSeparator === 'string', 'dirSeparator is not a String');
    assert(dirSeparator.length === 1, 'dirSeparator must be a single character');

    //encapsulate into DTOs
    var itemDTOs = items.map(function (item) {
        var path = iteratee(item);

        assert(typeof path === 'string', 'item or iteratee(item) must be a String');

        return {
            item: item,
            pathTokens: splitRetain(path, dirSeparator)
        };
    });

    //sort DTOs
    itemDTOs.sort(createItemDTOComparator(dirSeparator));

    //decapsulate sorted DTOs and return
    return itemDTOs.map(function (itemDTO) {
        return itemDTO.item;
    });
}
function sortPaths(items/* , [iteratee, ] dirSeparator */) {
    assert(arguments.length >= 2, 'too few arguments');
    assert(arguments.length <= 3, 'too many arguments');

    var iteratee, dirSeparator;

    if (arguments.length === 2) {
        iteratee = identity;
        dirSeparator = arguments[1];
    }
    else {
        iteratee = arguments[1];
        dirSeparator = arguments[2];
    }

    assert(isArray(items), 'items is not an array');
    assert(isFunction(iteratee), 'iteratee is not a function');
    assert(typeof dirSeparator === 'string', 'dirSeparator is not a String');
    assert(dirSeparator.length === 1, 'dirSeparator must be a single character');

    //encapsulate into DTOs
    var itemDTOs = items.map(function (item) {
        var path = iteratee(item);

        assert(typeof path === 'string', 'item or iteratee(item) must be a String');

        return {
            item: item,
            pathTokens: splitRetain(path, dirSeparator)
        };
    });

    //sort DTOs
    itemDTOs.sort(createItemDTOComparator(dirSeparator));

    //decapsulate sorted DTOs and return
    return itemDTOs.map(function (itemDTO) {
        return itemDTO.item;
    });
}
function sortPaths ( items /* , [iteratee, ] dirSeparator */ ) { assert ( arguments . length >= 2 , 'too few arguments' ) ; assert ( arguments . length <= 3 , 'too many arguments' ) ; var iteratee , dirSeparator ; if ( arguments . length === 2 ) { iteratee = identity ; dirSeparator = arguments [ 1 ] ; } else { iteratee = arguments [ 1 ] ; dirSeparator = arguments [ 2 ] ; } assert ( isArray ( items ) , 'items is not an array' ) ; assert ( isFunction ( iteratee ) , 'iteratee is not a function' ) ; assert ( typeof dirSeparator === 'string' , 'dirSeparator is not a String' ) ; assert ( dirSeparator . length === 1 , 'dirSeparator must be a single character' ) ; //encapsulate into DTOs var itemDTOs = items . map ( function ( item ) { var path = iteratee ( item ) ; assert ( typeof path === 'string' , 'item or iteratee(item) must be a String' ) ; return { item : item , pathTokens : splitRetain ( path , dirSeparator ) } ; } ) ; //sort DTOs itemDTOs . sort ( createItemDTOComparator ( dirSeparator ) ) ; //decapsulate sorted DTOs and return return itemDTOs . map ( function ( itemDTO ) { return itemDTO . item ; } ) ; }
Allows sorting arbitrary items without modifying or copying them

@typedef {Object} itemDTO

@param {String|Object} item - original item
@param {Array} pathTokens - split path tokens. Extracted from `item` using `iteratee` and split using `splitRetain`
Allows sorting arbitrary items without modifying or copying them