2018-03-19 01:12:18 +01:00
|
|
|
/** @module util *//***/
|
2018-03-17 23:41:48 +01:00
|
|
|
|
2017-12-24 03:19:47 +01:00
|
|
|
import {
|
|
|
|
CharCode
|
|
|
|
} from "./charcode";
|
2017-10-02 12:52:15 +02:00
|
|
|
|
2019-02-22 15:03:33 +02:00
|
|
|
import {
|
|
|
|
PATH_DELIMITER
|
|
|
|
} from "../common";
|
|
|
|
|
2018-02-02 03:07:54 +01:00
|
|
|
const separator = CharCode.SLASH;
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
/**
|
|
|
|
* Normalizes the specified path, removing interior placeholders.
|
|
|
|
* Expects a posix-compatible relative path (not Windows compatible).
|
|
|
|
*/
|
2018-03-19 01:12:18 +01:00
|
|
|
export function normalizePath(path: string): string {
|
2017-12-28 04:09:40 +01:00
|
|
|
var pos = 0;
|
|
|
|
var len = path.length;
|
2017-10-02 12:52:15 +02:00
|
|
|
|
|
|
|
// trim leading './'
|
2018-02-16 11:55:13 +01:00
|
|
|
while (pos + 1 < len &&
|
|
|
|
path.charCodeAt(pos) == CharCode.DOT &&
|
|
|
|
path.charCodeAt(pos + 1) == separator
|
|
|
|
) {
|
2017-10-02 12:52:15 +02:00
|
|
|
pos += 2;
|
2018-02-16 11:55:13 +01:00
|
|
|
}
|
2017-10-02 12:52:15 +02:00
|
|
|
|
|
|
|
if (pos > 0 || len < path.length) {
|
|
|
|
path = path.substring(pos, len);
|
|
|
|
len -= pos;
|
|
|
|
pos = 0;
|
|
|
|
}
|
|
|
|
|
2017-12-28 04:09:40 +01:00
|
|
|
var atEnd: bool;
|
2017-10-02 12:52:15 +02:00
|
|
|
while (pos + 1 < len) {
|
|
|
|
atEnd = false;
|
|
|
|
|
|
|
|
// we are only interested in '/.' sequences ...
|
2018-02-16 11:55:13 +01:00
|
|
|
if (
|
|
|
|
path.charCodeAt(pos) == separator &&
|
|
|
|
path.charCodeAt(pos + 1) == CharCode.DOT
|
|
|
|
) {
|
2017-10-02 12:52:15 +02:00
|
|
|
// '/.' ( '/' | $ )
|
2018-02-16 11:55:13 +01:00
|
|
|
atEnd = pos + 2 == len;
|
|
|
|
if (atEnd ||
|
|
|
|
pos + 2 < len &&
|
|
|
|
path.charCodeAt(pos + 2) == separator
|
2017-10-02 12:52:15 +02:00
|
|
|
) {
|
|
|
|
path = atEnd
|
|
|
|
? path.substring(0, pos)
|
|
|
|
: path.substring(0, pos) + path.substring(pos + 2);
|
|
|
|
len -= 2;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// '/.' ( './' | '.' $ )
|
2018-02-16 11:55:13 +01:00
|
|
|
atEnd = pos + 3 == len;
|
|
|
|
if (atEnd && path.charCodeAt(pos + 2) == CharCode.DOT ||
|
|
|
|
pos + 3 < len &&
|
|
|
|
path.charCodeAt(pos + 2) == CharCode.DOT &&
|
|
|
|
path.charCodeAt(pos + 3) == separator
|
2017-10-02 12:52:15 +02:00
|
|
|
) {
|
|
|
|
// find preceeding '/'
|
2018-03-13 02:32:10 +01:00
|
|
|
let ipos = pos;
|
2017-10-02 12:52:15 +02:00
|
|
|
while (--ipos >= 0) {
|
|
|
|
if (path.charCodeAt(ipos) == separator) {
|
2018-02-16 11:55:13 +01:00
|
|
|
if (pos - ipos != 3 ||
|
|
|
|
path.charCodeAt(ipos + 1) != CharCode.DOT ||
|
|
|
|
path.charCodeAt(ipos + 2) != CharCode.DOT
|
|
|
|
) { // exclude '..' itself
|
2017-10-02 12:52:15 +02:00
|
|
|
path = atEnd
|
|
|
|
? path.substring(0, ipos)
|
|
|
|
: path.substring(0, ipos) + path.substring(pos + 3);
|
|
|
|
len -= pos + 3 - ipos;
|
|
|
|
pos = ipos - 1; // incremented again at end of loop
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// if there's no preceeding '/', trim start if non-empty
|
|
|
|
if (ipos < 0 && pos > 0) {
|
2018-02-16 11:55:13 +01:00
|
|
|
if (pos != 2 ||
|
|
|
|
path.charCodeAt(0) != CharCode.DOT ||
|
|
|
|
path.charCodeAt(1) != CharCode.DOT
|
|
|
|
) { // exclude '..' itself
|
2017-10-02 12:52:15 +02:00
|
|
|
path = path.substring(pos + 4);
|
|
|
|
len = path.length;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pos++;
|
|
|
|
}
|
|
|
|
return len > 0 ? path : ".";
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:55:13 +01:00
|
|
|
/** Resolves the specified path relative to the specified origin. */
|
2018-03-19 01:12:18 +01:00
|
|
|
export function resolvePath(normalizedPath: string, origin: string): string {
|
2018-02-25 00:13:39 +01:00
|
|
|
if (normalizedPath.startsWith("std/")) {
|
2018-01-28 19:33:05 +01:00
|
|
|
return normalizedPath;
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
2018-03-19 01:12:18 +01:00
|
|
|
return normalizePath(
|
2019-02-22 15:03:33 +02:00
|
|
|
dirname(origin) + PATH_DELIMITER + normalizedPath
|
2018-02-16 11:55:13 +01:00
|
|
|
);
|
2017-10-02 12:52:15 +02:00
|
|
|
}
|
|
|
|
|
2017-12-18 03:46:36 +01:00
|
|
|
/** Obtains the directory portion of a normalized path. */
|
2018-02-02 03:07:54 +01:00
|
|
|
export function dirname(normalizedPath: string): string {
|
2017-12-28 04:09:40 +01:00
|
|
|
var pos = normalizedPath.length;
|
2019-02-22 15:03:33 +02:00
|
|
|
if (pos <= 1) {
|
|
|
|
if (pos == 0) return ".";
|
|
|
|
if (normalizedPath.charCodeAt(0) == separator) {
|
|
|
|
return normalizedPath;
|
|
|
|
}
|
|
|
|
}
|
2018-02-25 00:13:39 +01:00
|
|
|
while (--pos > 0) {
|
|
|
|
if (normalizedPath.charCodeAt(pos) == separator) {
|
2017-10-02 12:52:15 +02:00
|
|
|
return normalizedPath.substring(0, pos);
|
2018-02-25 00:13:39 +01:00
|
|
|
}
|
|
|
|
}
|
2017-10-02 12:52:15 +02:00
|
|
|
return ".";
|
|
|
|
}
|