From c480eca0290315905e7485470e29c66065705fff Mon Sep 17 00:00:00 2001 From: joshuaboud Date: Tue, 21 Jun 2022 17:22:29 -0300 Subject: [PATCH] add function to get common abs path and list of relative paths from list of abs paths --- navigator/src/functions/commonPath.js | 25 ++++++++++ navigator/src/functions/commonPath.test.js | 54 ++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 navigator/src/functions/commonPath.js create mode 100644 navigator/src/functions/commonPath.test.js diff --git a/navigator/src/functions/commonPath.js b/navigator/src/functions/commonPath.js new file mode 100644 index 0000000..390ef75 --- /dev/null +++ b/navigator/src/functions/commonPath.js @@ -0,0 +1,25 @@ +/** + * Get greatest common denomincator path of an array of input paths + * @param {string[]} paths - Full paths from which to get common denominator + * @returns {CommonPathObj} + */ +export function commonPath(paths) { + const pathArrs = paths.map(str => str.split('/')); + let commonArr = [...pathArrs[0]]; + for (let i = 0; i < pathArrs.length; i++) { + const iDiffer = pathArrs[i].findIndex((segment, index) => segment !== commonArr[index]); + if (iDiffer !== -1) + commonArr = commonArr.slice(0, iDiffer); + if (commonArr.length <= 1) + break; + } + const common = commonArr.join('/').replace(/^(?!\/)/, '/'); + const relativePaths = pathArrs.map(fullArr => fullArr.slice(commonArr.length).join('/') || '.'); + return { common, relativePaths }; +} + +/** + * @typedef {Object} CommonPathObj + * @property {string} common - The common denominator of all paths provided + * @property {string[]} relativePaths - the input paths made relative to the common path + */ diff --git a/navigator/src/functions/commonPath.test.js b/navigator/src/functions/commonPath.test.js new file mode 100644 index 0000000..e1f05e4 --- /dev/null +++ b/navigator/src/functions/commonPath.test.js @@ -0,0 +1,54 @@ +import { commonPath } from "./commonPath"; + +describe('The commonPath function', () => { + const filesInTmpTest = [ + '/tmp/test/file1', + '/tmp/test/file2', + '/tmp/test/subdir/file3', + ]; + const filesInTmpHello = [ + '/tmp/hello/file1', + '/tmp/hello/file2', + '/tmp/hello/subdir/file3', + ]; + const filesInTmp = [ + ...filesInTmpTest, + ...filesInTmpHello, + ]; + const filesInHome = [ + '/home/jboudreau/test1', + '/home/jboudreau/test2', + '/home/jboudreau/test3', + '/home/jboudreau/test/1/2/3/4', + '/home/mhooper/1/2/3/4', + ] + const allFiles = [ + ...filesInTmp, + ...filesInHome, + '/file', + '/', + ] + it('can get the expected common denominator path from a list of inputs', () => { + expect(commonPath(filesInTmpTest).common).toEqual('/tmp/test'); + expect(commonPath(filesInTmpHello).common).toEqual('/tmp/hello'); + expect(commonPath(filesInTmp).common).toEqual('/tmp'); + expect(commonPath(filesInHome).common).toEqual('/home'); + expect(commonPath(allFiles).common).toEqual('/'); + }); + + it('can properly generate relative paths s.t. common + / + relativePath === path', () => { + const testPaths = (paths) => { + const { common, relativePaths } = commonPath(paths); + for (let i = 0; i < relativePaths.length; i++) { + expect(relativePaths[i][0]).not.toEqual('/'); + expect(relativePaths[i].length).toBeGreaterThanOrEqual(1); + expect(`${common}/${relativePaths[i]}`.replace(/\/+/g, '/').replace(/(?<=\/)\.$/, '')).toEqual(paths[i]); + } + } + testPaths(filesInTmpTest); + testPaths(filesInTmpHello); + testPaths(filesInTmp); + testPaths(filesInHome); + testPaths(allFiles); + }); +})