2020-03-27 14:01:27 +08:00

174 lines
3.9 KiB
TypeScript

/**
* Check whether a component is external package, e.g. @ali/uxcore
* @param path Component path
*/
export function isPackagePath(path: string): boolean {
return !path.startsWith('.') && !path.startsWith('/');
}
/**
* Title cased string
* @param s original string
*/
export function toTitleCase(s: string): string {
return s
.split(/[-_ .]+/)
.map(token => token[0].toUpperCase() + token.substring(1))
.join('');
}
/**
* Make up an import name/tag for components
* @param path Original path name
*/
export function generateComponentName(path: string): string {
const parts = path.split('/');
let name = parts.pop();
if (name && /^index\./.test(name)) {
name = parts.pop();
}
return name ? toTitleCase(name) : 'Component';
}
/**
* normalizing import path for easier comparison
*/
export function getNormalizedImportPath(path: string): string {
const segments = path.split('/');
let basename = segments.pop();
if (!basename) {
return path;
}
const ignoredExtensions = ['.ts', '.js', '.tsx', '.jsx'];
const extIndex = basename.lastIndexOf('.');
if (extIndex > -1) {
const ext = basename.slice(extIndex);
if (ignoredExtensions.includes(ext)) {
basename = basename.slice(0, extIndex);
}
}
if (basename !== 'index') {
segments.push(basename);
}
return segments.join('/');
}
/**
* make a relative path
*
* @param toPath abolute path
* @param fromPath absolute path
*/
export function makeRelativePath(toPath: string, fromPath: string) {
// not a absolute path, eg. @ali/uxcore
if (!toPath.startsWith('/')) {
return toPath;
}
const toParts = toPath.split('/');
const fromParts = fromPath.split('/');
// find shared path header
const length = Math.min(fromParts.length, toParts.length);
let sharedUpTo = length;
for (let i = 0; i < length; i++) {
if (fromParts[i] !== toParts[i]) {
sharedUpTo = i;
break;
}
}
// find how many levels to go up from
// minus another 1 since we do not include the final
const numGoUp = fromParts.length - sharedUpTo - 1;
// generate final path
let outputParts = [];
if (numGoUp === 0) {
// in the same dir
outputParts.push('.');
} else {
// needs to go up
for (let i = 0; i < numGoUp; ++i) {
outputParts.push('..');
}
}
outputParts = outputParts.concat(toParts.slice(sharedUpTo));
return outputParts.join('/');
}
function normalizeArray(parts: string[], allowAboveRoot: boolean) {
const res = [];
for (let i = 0; i < parts.length; i++) {
const p = parts[i];
// ignore empty parts
if (!p || p === '.') {
continue;
}
if (p === '..') {
if (res.length && res[res.length - 1] !== '..') {
res.pop();
} else if (allowAboveRoot) {
res.push('..');
}
} else {
res.push(p);
}
}
return res;
}
function normalize(path: string): string {
const isAbsolute = path[0] === '/';
const segments = normalizeArray(path.split('/'), !isAbsolute);
if (isAbsolute) {
segments.unshift('');
} else if (segments.length < 1 || segments[0] !== '..') {
segments.unshift('.');
}
return segments.join('/');
}
/**
* Resolve component with absolute path to relative path
* @param path absolute path of component from project
*/
export function resolveAbsoluatePath(path: string, base: string): string {
if (!path.startsWith('.')) {
// eg. /usr/path/to, @ali/button
return path;
}
path = path.replace(/\\/g, '/');
if (base.slice(-1) !== '/') {
base += '/';
}
return normalize(base + path);
}
export function joinPath(...segments: string[]) {
let path = '';
for (const seg of segments) {
if (seg) {
if (path === '') {
path += seg;
} else {
path += '/' + seg;
}
}
}
return normalize(path);
}
export function removeVersion(path: string): string {
if (path.lastIndexOf('@') > 0) {
path = path.replace(/(@?[^@]+)(@[\w.-]+)(.+)/, '$1$3');
}
return path;
}