-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Replace polyfill with own path implementation
Remove the need for browserify packages due to security alerts from unused polyfills
- Loading branch information
1 parent
2c09ab0
commit bbced59
Showing
10 changed files
with
314 additions
and
763 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { Brand } from '@/@types/Brand.js' | ||
|
||
export type FilePathWithoutRst = Brand<string, 'FilePathWithoutRst'> | ||
|
||
export function getFilePathWithoutRst(filePath: string): FilePathWithoutRst { | ||
const pathWithoutExt = /^(?<pathWithoutExt>.+?)(?:\.rst)?$/.exec(filePath)?.groups?.pathWithoutExt ?? filePath | ||
return pathWithoutExt as FilePathWithoutRst | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
// ---------------------------------------------------------------------------- | ||
// MARK: getPathDirname | ||
// Replace path.dirname | ||
// ---------------------------------------------------------------------------- | ||
|
||
export function getPathDirname(path: string): string { | ||
if (path.length === 0) { | ||
return '.' | ||
} | ||
|
||
const isAbsolute = path.at(0) === '/' | ||
|
||
// Iterate BACKWARDS and stop when we find first slash preceding non-path-separator | ||
// e.g. Stop on first slash after after seeing `b` | ||
// `/a/b` -> `/a` | ||
// `/a/b/` -> `/a` | ||
let dirnameSlashIdx: number | null = null | ||
let sawNonPathSeparator = false | ||
|
||
for (let i = path.length - 1; i >= 1; i--) { | ||
const currChar = path.charAt(i) | ||
if (currChar !== '/') { | ||
sawNonPathSeparator = true | ||
continue | ||
} | ||
|
||
// currChar === '/' | ||
// If we already see non-path-separator, then we can terminate the search | ||
if (sawNonPathSeparator) { | ||
dirnameSlashIdx = i | ||
break | ||
} | ||
} | ||
|
||
// Search failed, then path is empty | ||
if (dirnameSlashIdx === null) { | ||
return isAbsolute ? '/' : '.' | ||
} | ||
|
||
// Special case of UNC path (`//abc` should return `//`) | ||
if (isAbsolute && dirnameSlashIdx === 1) { | ||
return '//' | ||
} | ||
|
||
return path.slice(0, dirnameSlashIdx) | ||
} | ||
|
||
// ---------------------------------------------------------------------------- | ||
// MARK: joinFilePath | ||
// Replace path.join | ||
// ---------------------------------------------------------------------------- | ||
|
||
export function joinFilePath(...args: Array<string>): string { | ||
let joined = '' | ||
|
||
for (const arg of args) { | ||
if (!arg) { | ||
continue | ||
} | ||
|
||
if (joined.length === 0) { | ||
joined = arg | ||
} else { | ||
joined += `/${arg}` | ||
} | ||
} | ||
|
||
return normalizeFilePath(joined) | ||
} | ||
|
||
// ---------------------------------------------------------------------------- | ||
// MARK: resolveFilePath | ||
// Replace path.resolve | ||
// ---------------------------------------------------------------------------- | ||
|
||
export function resolveFilePath(...args: Array<string>): string { | ||
let resolvedPath = '' | ||
let lastFragmentWasAbsolute = false | ||
|
||
// Iterate backwards and construct the resolved path | ||
for (let i = args.length - 1; i >= 0 && !lastFragmentWasAbsolute; i--) { | ||
const currPathFragment = args[i] | ||
if (!currPathFragment) { | ||
continue | ||
} | ||
|
||
if (resolvedPath.length === 0) { | ||
resolvedPath = currPathFragment | ||
} else { | ||
resolvedPath = currPathFragment + '/' + resolvedPath | ||
} | ||
|
||
lastFragmentWasAbsolute = currPathFragment.charAt(0) === '/' | ||
} | ||
|
||
// Use normalizeString instead of normalizeFilePath because | ||
// path.resolve is defined to trim trailing slash whereas normalizeFilePath preserves trailing slash | ||
resolvedPath = normalizeString(resolvedPath, lastFragmentWasAbsolute) | ||
|
||
if (lastFragmentWasAbsolute) { | ||
return `/${resolvedPath}` | ||
} | ||
if (resolvedPath.length === 0) { | ||
return '.' | ||
} | ||
|
||
return resolvedPath | ||
} | ||
|
||
// ---------------------------------------------------------------------------- | ||
// MARK: normalizeFilePath | ||
// Replace path.normalize | ||
// ---------------------------------------------------------------------------- | ||
|
||
export function normalizeFilePath(path: string): string { | ||
if (path.length === 0) { | ||
return '.' | ||
} | ||
if (path.length === 1) { | ||
return path | ||
} | ||
|
||
const isAbsolute = path.charAt(0) === '/' | ||
const hasTrailingSlash = path.charAt(path.length - 1) === '/' | ||
|
||
let resultPath = normalizeString(path, isAbsolute) | ||
if (resultPath.length === 0) { | ||
if (isAbsolute) { | ||
return '/' | ||
} else { | ||
if (hasTrailingSlash) { | ||
return './' | ||
} else { | ||
return '.' | ||
} | ||
} | ||
} | ||
|
||
if (isAbsolute) { | ||
resultPath = `/${resultPath}` | ||
} | ||
if (hasTrailingSlash) { | ||
resultPath = `${resultPath}/` | ||
} | ||
|
||
return resultPath | ||
} | ||
|
||
function normalizeString(path: string, isAbsolute: boolean): string { | ||
const parts = path.split('/').filter((part) => part.length > 0) | ||
const outputStack = new Array<string>() | ||
|
||
for (let i = 0; i < parts.length; i++) { | ||
const currPart = parts.at(i) | ||
|
||
// Skip over repeated slashes e.g. `////` | ||
if (!currPart) { | ||
continue | ||
} | ||
|
||
// Skip over single dots e.g. `/./` | ||
if (currPart === '.') { | ||
continue | ||
} | ||
|
||
// Skip over double dots and pop off previous part off stack | ||
if (currPart === '..') { | ||
switch (true) { | ||
// Unless: | ||
case !isAbsolute && outputStack.length === 0: // Original path is relative path and output is currently empty (at the start) | ||
case outputStack.at(-1) === '..': // Already has '..' on the stack (i.e. continuing relative ../../../) | ||
break | ||
|
||
default: { | ||
outputStack.pop() | ||
continue | ||
} | ||
} | ||
} | ||
|
||
outputStack.push(currPart) | ||
} | ||
|
||
return outputStack.join('/') | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { getFilePathWithoutRst } from '@/Generator/FilePathWithoutRst.js' | ||
import { expect, test } from 'vitest' | ||
|
||
test('when file path includes rst file extension, it removes the extension', () => { | ||
const input = '/hello/world/mydoc.rst' | ||
const output = '/hello/world/mydoc' | ||
expect(getFilePathWithoutRst(input)).toBe(output) | ||
}) | ||
|
||
test('when file path does not include rst file extension, it returns the original string', () => { | ||
const input = '/hello/world/mydoc' | ||
expect(getFilePathWithoutRst(input)).toBe(input) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import { expect, test, describe } from 'vitest' | ||
import { getPathDirname, joinFilePath, resolveFilePath } from '@/utils/path.js' | ||
|
||
// ---------------------------------------------------------------------------- | ||
// MARK: getPathDirname | ||
// ---------------------------------------------------------------------------- | ||
|
||
describe('getPathDirname', () => { | ||
test.each([ | ||
['/a/b/', '/a'], | ||
['/a/b', '/a'], | ||
['/a', '/'], | ||
['', '.'], | ||
['/', '/'], | ||
['////', '/'], | ||
['//a', '//'], | ||
['a', '.'], | ||
])('"%s" dirname = "%s"', (input, expectedOutput) => { | ||
expect(getPathDirname(input)).toBe(expectedOutput) | ||
}) | ||
}) | ||
|
||
// ---------------------------------------------------------------------------- | ||
// MARK: joinFilePath | ||
// ---------------------------------------------------------------------------- | ||
|
||
describe('joinFilePath', () => { | ||
test.each([ | ||
[['.', 'x/b', '..', '/b/c.js'], 'x/b/c.js'], | ||
[[], '.'], | ||
[['/.', 'x/b', '..', '/b/c.js'], '/x/b/c.js'], | ||
[['/foo', '../../../bar'], '/bar'], | ||
[['foo', '../../../bar'], '../../bar'], | ||
[['foo/', '../../../bar'], '../../bar'], | ||
[['foo/x', '../../../bar'], '../bar'], | ||
[['foo/x', './bar'], 'foo/x/bar'], | ||
[['foo/x/', './bar'], 'foo/x/bar'], | ||
[['foo/x/', '.', 'bar'], 'foo/x/bar'], | ||
[['./'], './'], | ||
[['.', './'], './'], | ||
[['.', '.', '.'], '.'], | ||
[['.', './', '.'], '.'], | ||
[['.', '/./', '.'], '.'], | ||
[['.', '/////./', '.'], '.'], | ||
[['.'], '.'], | ||
[['', '.'], '.'], | ||
[['', 'foo'], 'foo'], | ||
[['foo', '/bar'], 'foo/bar'], | ||
[['', '/foo'], '/foo'], | ||
[['', '', '/foo'], '/foo'], | ||
[['', '', 'foo'], 'foo'], | ||
[['foo', ''], 'foo'], | ||
[['foo/', ''], 'foo/'], | ||
[['foo', '', '/bar'], 'foo/bar'], | ||
[['./', '..', '/foo'], '../foo'], | ||
[['./', '..', '..', '/foo'], '../../foo'], | ||
[['.', '..', '..', '/foo'], '../../foo'], | ||
[['', '..', '..', '/foo'], '../../foo'], | ||
[['/'], '/'], | ||
[['/', '.'], '/'], | ||
[['/', '..'], '/'], | ||
[['/', '..', '..'], '/'], | ||
[[''], '.'], | ||
[['', ''], '.'], | ||
[[' /foo'], ' /foo'], | ||
[[' ', 'foo'], ' /foo'], | ||
[[' ', '.'], ' '], | ||
[[' ', '/'], ' /'], | ||
[[' ', ''], ' '], | ||
[['/', 'foo'], '/foo'], | ||
[['/', '/foo'], '/foo'], | ||
[['/', '//foo'], '/foo'], | ||
[['/', '', '/foo'], '/foo'], | ||
[['', '/', 'foo'], '/foo'], | ||
[['', '/', '/foo'], '/foo'], | ||
])('%s joins to "%s"', (input, expectedOutput) => { | ||
expect(joinFilePath(...input)).toBe(expectedOutput) | ||
}) | ||
}) | ||
|
||
// ---------------------------------------------------------------------------- | ||
// MARK: resolveFilePath | ||
// ---------------------------------------------------------------------------- | ||
|
||
describe('resolveFilePath', () => { | ||
test.each([ | ||
[['/var/lib', '../', 'file/'], '/var/file'], | ||
[['/var/lib', '/../', 'file/'], '/file'], | ||
[['a/b/c/', '../../..'], '.'], | ||
[['.'], '.'], | ||
[['/some/dir', '.', '/absolute/'], '/absolute'], | ||
[['/foo/tmp.3/', '../tmp.3/cycles/root.js'], '/foo/tmp.3/cycles/root.js'], | ||
])('%s resolves to "%s"', (input, expectedOutput) => { | ||
expect(resolveFilePath(...input)).toBe(expectedOutput) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.