Skip to content

Commit 77e0b13

Browse files
committed
feat: extToValue
Signed-off-by: Lexus Drumgold <unicornware@flexdevelopment.llc>
1 parent f8ea637 commit 77e0b13

File tree

7 files changed

+156
-0
lines changed

7 files changed

+156
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ import {
9292
delimiter,
9393
dirname,
9494
dot,
95+
extToValue,
9596
extname,
9697
fileURLToPath,
9798
format,
@@ -128,6 +129,7 @@ This package exports the following identifiers:
128129
- [`delimiter`](./src/lib/delimiter.mts)
129130
- [`dirname`](./src/lib/dirname.mts)
130131
- [`dot`](./src/lib/dot.mts)
132+
- [`extToValue`](./src/lib/ext-to-value.mts)
131133
- [`extname`](./src/lib/extname.mts)
132134
- [`extnames`](./src/lib/extnames.mts)
133135
- [`fileURLToPath`](./src/lib/file-url-to-path.mts)

src/__snapshots__/index.e2e.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ exports[`e2e:pathe > should expose public api 1`] = `
99
"delimiter",
1010
"dirname",
1111
"dot",
12+
"extToValue",
1213
"extname",
1314
"extnames",
1415
"fileURLToPath",

src/interfaces/pathe.mts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,34 @@ interface Pathe extends PosixPlatformPath {
156156
*/
157157
readonly dot: Dot
158158

159+
/**
160+
* Get a value for `input` based on its file extension.
161+
*
162+
* This algorithm picks the value with the longest matching file extension,
163+
* so if `map` has the keys `'.mts'` and `'.d.mts'`, the value for `'.d.mts'`
164+
* will be returned.
165+
*
166+
* @see {@linkcode EmptyString}
167+
* @see {@linkcode Ext}
168+
*
169+
* @template {any} T
170+
* Map value
171+
*
172+
* @this {void}
173+
*
174+
* @param {URL | string} input
175+
* The {@linkcode URL}, URL string, or path to handle
176+
* @param {Partial<Record<EmptyString | Ext, T>>} map
177+
* Extension map
178+
* @return {T | undefined}
179+
* Value for `input` or `undefined`
180+
*/
181+
extToValue<T>(
182+
this: void,
183+
input: URL | string,
184+
map: Partial<Record<EmptyString | Ext, T>>
185+
): T | undefined
186+
159187
/**
160188
* Get a list of file extensions for `input`.
161189
*
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* @file Unit Tests - extToValue
3+
* @module pathe/lib/tests/unit/extToValue
4+
*/
5+
6+
import changeExt from '#lib/change-ext'
7+
import testSubject from '#lib/ext-to-value'
8+
import pathToFileURL from '#lib/path-to-file-url'
9+
import removeExt from '#lib/remove-ext'
10+
import type { EmptyString, Ext } from '@flex-development/pathe'
11+
import type { Loader } from 'esbuild'
12+
13+
describe('unit:lib/extToValue', () => {
14+
let map: Record<EmptyString | Ext, Loader>
15+
16+
beforeAll(() => {
17+
map = { '': 'ts', '.d.mts': 'copy', '.mts': 'ts', '.npmrc': 'copy' }
18+
})
19+
20+
it.each<[URL | string, Loader | undefined]>([
21+
['.npmrc', 'copy'],
22+
[changeExt(import.meta.url, 'cts'), undefined],
23+
[import.meta.url, 'ts'],
24+
[pathToFileURL('dist/lib/ext-to-value.d.mts'), 'copy'],
25+
[removeExt(import.meta.url, 'spec.mts'), 'ts']
26+
])('should return value based on file extension of `input` (%#)', (
27+
input,
28+
expected
29+
) => {
30+
expect(testSubject(input, map)).to.eq(expected)
31+
})
32+
})

src/lib/ext-to-value.mts

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/**
2+
* @file extToValue
3+
* @module pathe/lib/extToValue
4+
*/
5+
6+
import basename from '#lib/basename'
7+
import dot from '#lib/dot'
8+
import type { EmptyString, Ext } from '@flex-development/pathe'
9+
10+
/**
11+
* Get a value for `input` based on its file extension.
12+
*
13+
* This algorithm picks the value with the longest matching file extension,
14+
* so if `map` has the keys `'.mts'` and `'.d.mts'`, the value for `'.d.mts'`
15+
* will be returned.
16+
*
17+
* @see {@linkcode EmptyString}
18+
* @see {@linkcode Ext}
19+
*
20+
* @category
21+
* utils
22+
*
23+
* @template {any} T
24+
* Map value
25+
*
26+
* @this {void}
27+
*
28+
* @param {URL | string} input
29+
* The {@linkcode URL}, URL string, or path to handle
30+
* @param {Partial<Record<EmptyString | Ext, T>>} map
31+
* Extension map
32+
* @return {T | undefined}
33+
* Value based on file extension of `input`
34+
*/
35+
function extToValue<T>(
36+
this: void,
37+
input: URL | string,
38+
map: Partial<Record<EmptyString | Ext, T>>
39+
): T | undefined {
40+
/**
41+
* Basename to check.
42+
*
43+
* @var {string} base
44+
*/
45+
let base: string = basename(input)
46+
47+
/**
48+
* Index of {@linkcode dot}.
49+
*
50+
* @var {number} index
51+
*/
52+
let index: number = base.indexOf(dot)
53+
54+
/**
55+
* Current value.
56+
*
57+
* @var {T | undefined} value
58+
*/
59+
let value: T | undefined
60+
61+
if (index === -1) {
62+
value = map['']
63+
} else {
64+
while (true) {
65+
value = map[base.slice(index) as EmptyString | Ext]
66+
67+
if (value === undefined) {
68+
base = base.slice(index + 1)
69+
70+
/**
71+
* Next index of {@linkcode dot}.
72+
*
73+
* @const {number} nextIndex
74+
*/
75+
const nextIndex: number = base.indexOf(dot)
76+
77+
if (nextIndex !== -1) {
78+
index = nextIndex
79+
continue
80+
}
81+
}
82+
83+
break
84+
}
85+
}
86+
87+
return value
88+
}
89+
90+
export default extToValue

src/lib/index.mts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export { default as cwd } from '#lib/cwd'
1010
export { default as delimiter } from '#lib/delimiter'
1111
export { default as dirname } from '#lib/dirname'
1212
export { default as dot } from '#lib/dot'
13+
export { default as extToValue } from '#lib/ext-to-value'
1314
export { default as extname } from '#lib/extname'
1415
export { default as extnames } from '#lib/extnames'
1516
export { default as fileURLToPath } from '#lib/file-url-to-path'

src/pathe.mts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
delimiter,
1313
dirname,
1414
dot,
15+
extToValue,
1516
extname,
1617
extnames,
1718
fileURLToPath,
@@ -113,6 +114,7 @@ const pathe: Pathe = {
113114
delimiter,
114115
dirname,
115116
dot,
117+
extToValue,
116118
extname,
117119
extnames,
118120
fileURLToPath,

0 commit comments

Comments
 (0)