Skip to content

Commit

Permalink
feat!: implement rest of path minimally (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielroe committed May 5, 2022
1 parent 02b9c75 commit 6136b3c
Show file tree
Hide file tree
Showing 6 changed files with 408 additions and 644 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ jobs:
cache: yarn
- run: yarn install
- run: yarn lint
- run: yarn test
- run: yarn test --coverage
13 changes: 5 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,18 @@
"build": "siroc build",
"lint": "eslint --ext .ts .",
"prepublishOnly": "yarn build",
"release": "yarn test && standard-version && git push --follow-tags && npm publish",
"test": "nyc mocha -r jiti/register test/*"
"release": "yarn vitest run && standard-version && git push --follow-tags && npm publish",
"test": "vitest"
},
"devDependencies": {
"@nuxtjs/eslint-config-typescript": "latest",
"@types/chai": "^4.2.22",
"@types/mocha": "^9.0.0",
"@types/node": "^16.9.6",
"chai": "^4.3.4",
"c8": "^7.11.2",
"eslint": "latest",
"jiti": "^1.12.3",
"mocha": "^9.1.1",
"nyc": "^15.1.0",
"siroc": "latest",
"standard-version": "latest",
"typescript": "^4.4.3"
"typescript": "^4.4.3",
"vitest": "^0.10.2"
}
}
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Reference https://nodejs.org/api/path.html
import path from 'path'
import type path from 'path'

import * as _path from './path'
export * from './path'
Expand Down
34 changes: 26 additions & 8 deletions src/path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ Check LICENSE file
*/

// TODO: Progressively remove path dependency
import path from 'path'
import type path from 'path'

import { normalizeWindowsPath } from './utils'

Expand Down Expand Up @@ -184,30 +183,49 @@ export const toNamespacedPath: typeof path.toNamespacedPath = function (p) {

// extname
export const extname: typeof path.extname = function (p) {
return path.posix.extname(normalizeWindowsPath(p))
const segments = normalizeWindowsPath(p).split('/').pop().split('.')
return segments.length > 1 ? `.${segments.pop()}` : ''
}

// relative
export const relative: typeof path.relative = function (from, to) {
return path.posix.relative(normalizeWindowsPath(from), normalizeWindowsPath(to))
const _from = resolve(from).split('/')
const _to = resolve(to).split('/')
for (const segment of [..._from]) {
if (_to[0] !== segment) { break }
_from.shift()
_to.shift()
}
return [..._from.map(() => '..'), ..._to].join('/')
}

// dirname
export const dirname: typeof path.dirname = function (p) {
return path.posix.dirname(normalizeWindowsPath(p))
return normalizeWindowsPath(p).replace(/\/$/, '').split('/').slice(0, -1).join('/') || '/'
}

// format
export const format: typeof path.format = function (p) {
return normalizeWindowsPath(path.posix.format(p))
const segments = [p.root, p.dir, p.base ?? (p.name + p.ext)].filter(Boolean)
return normalizeWindowsPath(p.root ? resolve(...segments) : segments.join('/'))
}

// basename
export const basename: typeof path.basename = function (p, ext) {
return path.posix.basename(normalizeWindowsPath(p), ext)
const lastSegment = normalizeWindowsPath(p).split('/').pop()
return lastSegment.endsWith(ext) ? lastSegment.slice(0, -ext.length) : lastSegment
}

// parse
export const parse: typeof path.parse = function (p) {
return path.posix.parse(normalizeWindowsPath(p))
const root = normalizeWindowsPath(p).split('/').shift() || '/'
const base = basename(p)
const ext = extname(base)
return {
root,
dir: dirname(p),
base,
ext,
name: base.slice(0, base.length - ext.length)
}
}
40 changes: 30 additions & 10 deletions test/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { expect } from 'chai'
import { describe, expect, it } from 'vitest'

import { basename, dirname, extname, format, parse, relative, delimiter, isAbsolute, join, normalize, resolve, sep, toNamespacedPath } from '../src'

Expand Down Expand Up @@ -29,23 +29,27 @@ runTest('isAbsolute', isAbsolute, {
'bar/baz': false
})

runTest('basename', basename, {
runTest('basename', basename, [
// POSIX
'C:\\temp\\myfile.html': 'myfile.html',
'\\temp\\myfile.html': 'myfile.html',
'.\\myfile.html': 'myfile.html',
['C:\\temp\\myfile.html', 'myfile.html'],
['\\temp\\myfile.html', 'myfile.html'],
['.\\myfile.html', 'myfile.html'],
['.\\myfile.html', '.html', 'myfile'],

// Windows
'/temp/myfile.html': 'myfile.html',
'./myfile.html': 'myfile.html'
})
['/temp/myfile.html', 'myfile.html'],
['./myfile.html', 'myfile.html'],
['./myfile.html', '.html', 'myfile']
])

runTest('dirname', dirname, {
// POSIX
'/temp/': '/',
'/temp/myfile.html': '/temp',
'./myfile.html': '.',

// Windows
'C:\\temp\\': 'C:',
'C:\\temp\\myfile.html': 'C:/temp',
'\\temp\\myfile.html': '/temp',
'.\\myfile.html': '.'
Expand All @@ -67,8 +71,10 @@ runTest('format', format, [
[{ root: '/ignored', dir: '/home/user/dir', base: 'file.txt' }, '/home/user/dir/file.txt'],
[{ root: '/', base: 'file.txt', ext: 'ignored' }, '/file.txt'],
[{ root: '/', name: 'file', ext: '.txt' }, '/file.txt'],
[{ name: 'file', ext: '.txt' }, 'file.txt'],

// Windows
[{ name: 'file', base: 'file.txt' }, 'file.txt'],
[{ dir: 'C:\\path\\dir', base: 'file.txt' }, 'C:/path/dir/file.txt']
])

Expand Down Expand Up @@ -126,15 +132,29 @@ it('parse', () => {
ext: '.txt',
name: 'file'
})
expect(parse('./dir/file')).to.deep.equal({
root: '.',
dir: './dir',
base: 'file',
ext: '',
name: 'file'
})

// Windows
expect(parse('C:\\path\\dir\\file.txt')).to.deep.equal({
root: '', // 'C:/',
root: 'C:',
dir: 'C:/path/dir',
base: 'file.txt',
ext: '.txt',
name: 'file'
})
expect(parse('.\\dir\\file')).to.deep.equal({
root: '.',
dir: './dir',
base: 'file',
ext: '',
name: 'file'
})
})

runTest('relative', relative, [
Expand Down Expand Up @@ -169,7 +189,7 @@ runTest('toNamespacedPath', toNamespacedPath, {
'C:\\foo\\bar': 'C:/foo/bar'
})

describe('contatants', () => {
describe('constants', () => {
it('delimiter should equal :', () => {
expect(delimiter).to.equal(':')
})
Expand Down

0 comments on commit 6136b3c

Please sign in to comment.