Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add path.parse implement #46

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
87 changes: 86 additions & 1 deletion polyfills/path.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@
// must be no slashes, empty elements, or device names (c:\) in the array
// (so also no leading and trailing slashes - it does not distinguish
// relative and absolute paths)

function assertPath(path) {
if (typeof path !== 'string') {
throw new TypeError('Path must be a string. Received ' + JSON.stringify(path));
}
}

function normalizeArray(parts, allowAboveRoot) {
// if the path tries to go above the root, `up` ends up > 0
var up = 0;
Expand Down Expand Up @@ -203,6 +210,83 @@ export function basename(path, ext) {
export function extname(path) {
return splitPath(path)[3];
}

export function parse(path) {
assertPath(path);

var ret = { root: '', dir: '', base: '', ext: '', name: '' };
if (path.length === 0) return ret;
var code = path.charCodeAt(0);
var isAbsolute = code === 47 /*/*/;
var start;
if (isAbsolute) {
ret.root = '/';
start = 1;
} else {
start = 0;
}
var startDot = -1;
var startPart = 0;
var end = -1;
var matchedSlash = true;
var i = path.length - 1;

// Track the state of characters (if any) we see before our first dot and
// after any path separator we find
var preDotState = 0;

// Get non-dir info
for (; i >= start; --i) {
code = path.charCodeAt(i);
if (code === 47 /*/*/) {
// If we reached a path separator that was not part of a set of path
// separators at the end of the string, stop now
if (!matchedSlash) {
startPart = i + 1;
break;
}
continue;
}
if (end === -1) {
// We saw the first non-path separator, mark this as the end of our
// extension
matchedSlash = false;
end = i + 1;
}
if (code === 46 /*.*/) {
// If this is our first dot, mark it as the start of our extension
if (startDot === -1) startDot = i;else if (preDotState !== 1) preDotState = 1;
} else if (startDot !== -1) {
// We saw a non-dot and non-path separator before our dot, so we should
// have a good chance at having a non-empty extension
preDotState = -1;
}
}

if (startDot === -1 || end === -1 ||
// We saw a non-dot character immediately before the dot
preDotState === 0 ||
// The (right-most) trimmed path component is exactly '..'
preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
if (end !== -1) {
if (startPart === 0 && isAbsolute) ret.base = ret.name = path.slice(1, end);else ret.base = ret.name = path.slice(startPart, end);
}
} else {
if (startPart === 0 && isAbsolute) {
ret.name = path.slice(1, startDot);
ret.base = path.slice(1, end);
} else {
ret.name = path.slice(startPart, startDot);
ret.base = path.slice(startPart, end);
}
ret.ext = path.slice(startDot, end);
}

if (startPart > 0) ret.dir = path.slice(0, startPart - 1);else if (isAbsolute) ret.dir = '/';

return ret;
}

export default {
extname: extname,
basename: basename,
Expand All @@ -213,7 +297,8 @@ export default {
join: join,
isAbsolute: isAbsolute,
normalize: normalize,
resolve: resolve
resolve: resolve,
parse: parse,
};
function filter (xs, f) {
if (xs.filter) return xs.filter(f);
Expand Down
18 changes: 18 additions & 0 deletions test/examples/path-parse.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {parse} from 'path';

// test path.parse
var parseResult = parse('/home/user/dir/file.txt');
var expectedResult = {
root: '/',
dir: '/home/user/dir',
base: 'file.txt',
ext: '.txt',
name: 'file'
};
if (Object.keys(expectedResult).every(
key => expectedResult[key] === parseResult[key]
)) {
done();
} else {
done(new Error(`parse error, expected ${JSON.stringify(expectedResult)} but got '${JSON.stringify(parseResult)}'`));
}
1 change: 1 addition & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const files = [
'constants.js',
'os.js',
'path.js',
'path-parse.js',
'string-decoder.js',
'zlib.js',
'domain.js',
Expand Down