From ac56b6120d7327fc2654c51502f4bd32a1630276 Mon Sep 17 00:00:00 2001 From: Rory Bradford Date: Tue, 8 Apr 2014 22:48:24 +0100 Subject: [PATCH] path: added parse() and format() functions The parse() function splits a path and returns an object with the different elements. The format() function is the reverse of this and adds an objects corresponding path elements to make up a string. Fixes #6976. --- doc/api/path.markdown | 42 ++++++++++++++++++ lib/path.js | 49 ++++++++++++++++++++ test/simple/test-path-parse-format.js | 64 +++++++++++++++++++++++++++ 3 files changed, 155 insertions(+) create mode 100644 test/simple/test-path-parse-format.js diff --git a/doc/api/path.markdown b/doc/api/path.markdown index 054159533af7..c4468713abc8 100644 --- a/doc/api/path.markdown +++ b/doc/api/path.markdown @@ -202,6 +202,48 @@ An example on Windows: // returns ['C:\Windows\system32', 'C:\Windows', 'C:\Program Files\nodejs\'] +## path.parse + +Returns an object from a path string. + +An example on *nix: + + path.parse('/home/user/dir/file.txt') + // returns + { + root : "/", + dir : "/home/user/dir", + base : "file.txt", + ext : ".txt", + name : "file" + } + +An example on Windows: + + path.parse('C:\\path\\dir\\index.html') + // returns + { + root : "C:\", + dir : "C:\path\dir", + base : "index.html", + ext : ".html", + name : "index" + } + +## path.format + +Returns a path string from an object, the opposite of `path.parse` above. + + path.format({ + root : "/", + dir : "/home/user/dir", + base : "file.txt", + ext : ".txt", + name : "file" + }) + // returns + '/home/user/dir/file.txt' + ## path.posix Provide access to aforementioned `path` methods but always interact in a posix diff --git a/lib/path.js b/lib/path.js index 2cab82acd5e2..ffb02872aca6 100644 --- a/lib/path.js +++ b/lib/path.js @@ -54,6 +54,7 @@ function normalizeArray(parts, allowAboveRoot) { return parts; } +var splitPath; // Regex to split a windows path into three parts: [*, device, slash, // tail] windows-only @@ -364,6 +365,30 @@ win32.extname = function(path) { }; +win32.format = function(object) { + root = object.root || ''; + dir = object.dir; + base = object.base || ''; + if (dir.slice(dir.length - 1, dir.length) === win32.sep) { + return dir + base; + } else { + return dir + this.sep + base; + } +}; + + +win32.parse = function(string) { + var allParts = win32.splitPath(string); + return { + root: allParts[0], + dir: allParts[0] + allParts[1].slice(0, allParts[1].length - 1), + base: allParts[2], + ext: allParts[3], + name: allParts[2].slice(0, allParts[2].length - allParts[3].length) + }; +}; + + win32.sep = '\\'; win32.delimiter = ';'; @@ -545,6 +570,30 @@ posix.extname = function(path) { }; +posix.format = function(object) { + root = object.root || ''; + var sep = posix.sep; + if (root.indexOf(':') > -1) { + sep = '\\'; + } + dir = object.dir + sep; + base = object.base || ''; + return dir + base; +}; + + +posix.parse = function(string) { + var allParts = posix.splitPath(string); + return { + root: allParts[0], + dir: allParts[0] + allParts[1].slice(0, allParts[1].length - 1), + base: allParts[2], + ext: allParts[3], + name: allParts[2].slice(0, allParts[2].length - allParts[3].length) + }; +}; + + posix.sep = '/'; posix.delimiter = ':'; diff --git a/test/simple/test-path-parse-format.js b/test/simple/test-path-parse-format.js new file mode 100644 index 000000000000..e5759d07408c --- /dev/null +++ b/test/simple/test-path-parse-format.js @@ -0,0 +1,64 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var assert = require('assert'); +var path = require('path'); + +var winPaths = [ + 'C:\\path\\dir\\index.html', + 'C:\\another_path\\DIR\\1\\2\\33\\index', + 'another_path\\DIR with spaces\\1\\2\\33\\index', + + // unc + '\\\\server\\share\\file_path', + '\\\\server two\\shared folder\\file path.zip', + '\\\\teela\\admin$\\system32' + +]; + +var unixPaths = [ + '/home/user/dir/file.txt', + '/home/user/a dir/another File.zip', + '/home/user/a dir//another&File.', + '/home/user/a$$$dir//another File.zip', + 'user/dir/another File.zip' +]; + +check(path.win32, winPaths); +check(path.posix, unixPaths); + +function check(path, paths) { + paths.forEach(function(element, index, array) { + var count = index + 1; + console.log(count + ': `' + element + '`'); + var output = path.parse(element); + var keys = Object.keys(output); + var values = []; + for (var i = 0; i < Object.keys(output).length; i++) { + values.push(output[keys[i]]); + } + + assert.strictEqual(path.format(path.parse(element)), element); + assert.strictEqual(path.parse(element).dir, path.dirname(element)); + assert.strictEqual(path.parse(element).base, path.basename(element)); + assert.strictEqual(path.parse(element).ext, path.extname(element)); + }) +}