| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- export function stripFileProtocol(input: string) {
- if (!input.startsWith("file://")) return input
- return input.slice("file://".length)
- }
- export function stripQueryAndHash(input: string) {
- const hashIndex = input.indexOf("#")
- const queryIndex = input.indexOf("?")
- if (hashIndex !== -1 && queryIndex !== -1) {
- return input.slice(0, Math.min(hashIndex, queryIndex))
- }
- if (hashIndex !== -1) return input.slice(0, hashIndex)
- if (queryIndex !== -1) return input.slice(0, queryIndex)
- return input
- }
- export function unquoteGitPath(input: string) {
- if (!input.startsWith('"')) return input
- if (!input.endsWith('"')) return input
- const body = input.slice(1, -1)
- const bytes: number[] = []
- for (let i = 0; i < body.length; i++) {
- const char = body[i]!
- if (char !== "\\") {
- bytes.push(char.charCodeAt(0))
- continue
- }
- const next = body[i + 1]
- if (!next) {
- bytes.push("\\".charCodeAt(0))
- continue
- }
- if (next >= "0" && next <= "7") {
- const chunk = body.slice(i + 1, i + 4)
- const match = chunk.match(/^[0-7]{1,3}/)
- if (!match) {
- bytes.push(next.charCodeAt(0))
- i++
- continue
- }
- bytes.push(parseInt(match[0], 8))
- i += match[0].length
- continue
- }
- const escaped =
- next === "n"
- ? "\n"
- : next === "r"
- ? "\r"
- : next === "t"
- ? "\t"
- : next === "b"
- ? "\b"
- : next === "f"
- ? "\f"
- : next === "v"
- ? "\v"
- : next === "\\" || next === '"'
- ? next
- : undefined
- bytes.push((escaped ?? next).charCodeAt(0))
- i++
- }
- return new TextDecoder().decode(new Uint8Array(bytes))
- }
- export function createPathHelpers(scope: () => string) {
- const normalize = (input: string) => {
- const root = scope()
- const prefix = root.endsWith("/") ? root : root + "/"
- let path = unquoteGitPath(stripQueryAndHash(stripFileProtocol(input)))
- if (path.startsWith(prefix)) {
- path = path.slice(prefix.length)
- }
- if (path.startsWith(root)) {
- path = path.slice(root.length)
- }
- if (path.startsWith("./")) {
- path = path.slice(2)
- }
- if (path.startsWith("/")) {
- path = path.slice(1)
- }
- return path
- }
- const tab = (input: string) => {
- const path = normalize(input)
- return `file://${path}`
- }
- const pathFromTab = (tabValue: string) => {
- if (!tabValue.startsWith("file://")) return
- return normalize(tabValue)
- }
- const normalizeDir = (input: string) => normalize(input).replace(/\/+$/, "")
- return {
- normalize,
- tab,
- pathFromTab,
- normalizeDir,
- }
- }
|