From 1ece780a7568d2151c4f839481759997101a0e93 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Wed, 10 Aug 2022 15:56:23 +0100 Subject: [PATCH] feat: add `normalizeAliases` and `filename` in `/utils` subpath (#34) --- .github/workflows/ci.yml | 1 + package.json | 7 ++++++- src/_internal.ts | 7 +++++++ src/path.ts | 2 +- src/utils.ts | 33 +++++++++++++++++++++++++----- test/index.spec.ts | 2 +- test/utils.spec.ts | 43 ++++++++++++++++++++++++++++++++++++++++ tsconfig.json | 4 +++- 8 files changed, 90 insertions(+), 9 deletions(-) create mode 100644 src/_internal.ts create mode 100644 test/utils.spec.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3db5858..e1ff5e5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,5 +21,6 @@ jobs: - run: pnpm install - run: pnpm lint - run: pnpm build + - run: pnpm test:types - run: pnpm vitest --coverage - uses: codecov/codecov-action@v3 diff --git a/package.json b/package.json index 7b52404..2108852 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,10 @@ ".": { "import": "./dist/index.mjs", "require": "./dist/index.cjs" + }, + "./utils": { + "import": "./dist/utils.mjs", + "require": "./dist/utils.cjs" } }, "main": "./dist/index.cjs", @@ -22,7 +26,8 @@ "lint": "eslint --ext .ts .", "prepublishOnly": "pnpm build", "release": "pnpm vitest run && standard-version && git push --follow-tags && pnpm publish", - "test": "pnpm lint && vitest run --coverage" + "test": "pnpm lint && vitest run --coverage", + "test:types": "tsc --noEmit" }, "devDependencies": { "@nuxtjs/eslint-config-typescript": "latest", diff --git a/src/_internal.ts b/src/_internal.ts new file mode 100644 index 0000000..b998412 --- /dev/null +++ b/src/_internal.ts @@ -0,0 +1,7 @@ +// Util to normalize windows paths to posix +export function normalizeWindowsPath (input: string = '') { + if (!input || !input.includes('\\')) { + return input + } + return input.replace(/\\/g, '/') +} diff --git a/src/path.ts b/src/path.ts index 9912721..f613336 100644 --- a/src/path.ts +++ b/src/path.ts @@ -8,7 +8,7 @@ Check LICENSE file import type path from 'path' -import { normalizeWindowsPath } from './utils' +import { normalizeWindowsPath } from './_internal' const _UNC_REGEX = /^[\\/]{2}/ const _IS_ABSOLUTE_RE = /^[\\/](?![\\/])|^[\\/]{2}(?!\.)|^[a-zA-Z]:[\\/]/ diff --git a/src/utils.ts b/src/utils.ts index b998412..f0ae8ae 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,7 +1,30 @@ -// Util to normalize windows paths to posix -export function normalizeWindowsPath (input: string = '') { - if (!input || !input.includes('\\')) { - return input +const pathSeparators = ['/', '\\', undefined] + +export function normalizeAliases (_aliases: Record) { + // Sort aliases from specific to general (ie. fs/promises before fs) + const aliases = Object.fromEntries(Object.entries(_aliases).sort(([a], [b]) => _compareAliases(a, b))) + // Resolve alias values in relation to each other + for (const key in aliases) { + for (const alias in aliases) { + // don't resolve a more specific alias with regard to a less specific one + if (alias === key || key.startsWith(alias)) { continue } + + if (aliases[key].startsWith(alias) && pathSeparators.includes(aliases[key][alias.length])) { + aliases[key] = aliases[alias] + aliases[key].slice(alias.length) + } + } } - return input.replace(/\\/g, '/') + return aliases +} + +const FILENAME_RE = /(?<=^|[\\/])([^\\/]+?)(?=(\.[^.]+)?$)/ + +export function filename (path: string) { + return path.match(FILENAME_RE)?.[0] +} + +// --- internals --- + +function _compareAliases (a: string, b: string) { + return b.split('/').length - a.split('/').length } diff --git a/test/index.spec.ts b/test/index.spec.ts index 5eec768..5a5b3cc 100644 --- a/test/index.spec.ts +++ b/test/index.spec.ts @@ -2,7 +2,7 @@ import { describe, expect, it, vi } from 'vitest' import { basename, dirname, extname, format, parse, relative, delimiter, isAbsolute, join, normalize, resolve, sep, toNamespacedPath, normalizeString } from '../src' -import { normalizeWindowsPath } from '../src/utils' +import { normalizeWindowsPath } from '../src/_internal' runTest('normalizeWindowsPath', normalizeWindowsPath, { // POSIX diff --git a/test/utils.spec.ts b/test/utils.spec.ts new file mode 100644 index 0000000..93dd605 --- /dev/null +++ b/test/utils.spec.ts @@ -0,0 +1,43 @@ +import { describe, expect, it } from 'vitest' + +import { normalizeAliases, filename } from '../src/utils' + +describe('normalizeAliases', () => { + it('should work', () => { + expect(normalizeAliases({ + '@foo/bar': '@foo/bar/dist/index.mjs', + '@foo/bar/utils': '@foo/bar/dist/utils.mjs', + '@': '/root', + bingpot: '@/bingpot/index.ts', + unchanged: '@bingpot/index.ts' + })).toMatchInlineSnapshot(` + { + "@": "/root", + "@foo/bar": "@foo/bar/dist/index.mjs", + "@foo/bar/utils": "@foo/bar/dist/utils.mjs", + "bingpot": "/root/bingpot/index.ts", + "unchanged": "@bingpot/index.ts", + } + `) + }) +}) + +describe('filename', () => { + const files = { + // POSIX + 'test.html': 'test', + '/temp/myfile.html': 'myfile', + './myfile.html': 'myfile', + + // Windows + 'C:\\temp\\': undefined, + 'C:\\temp\\myfile.html': 'myfile', + '\\temp\\myfile.html': 'myfile', + '.\\myfile.html': 'myfile' + } + for (const file in files) { + it(file, () => { + expect(filename(file)).toEqual(files[file]) + }) + } +}) diff --git a/tsconfig.json b/tsconfig.json index 7ed9c46..a6b3f69 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,9 +3,11 @@ "target": "ESNext", "module": "ESNext", "moduleResolution": "Node", + "skipLibCheck": true, "esModuleInterop": true }, "include": [ - "src" + "src", + "test" ] }