All files / ts / unmap.ts

100.00% Branches 5/5
100.00% Lines 26/26
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
x1
x4
 
 
 
x4
x4
 
x4
x4
x22
x22
x22
x117
x39
x39
x48
x48
x58
x58
x58
x39
x50
x150
x50
x50
x45
x22
x88
x22



























// Imports
import { Logger } from "@libs/logger"
import type { Nullable, record } from "@libs/typing"
export type { record }

/** Regex for `imports` parsing. */
const regex = /^(?<statement>import\s*(?:(?:\s+type)?\s+(?:[^\n]+?|(?:\{[\s\S]*?\}))\s+from\s+)?(?<quote>["']))(?<module>[^\n]+?)\k<quote>/gm

/** Resolves all imports from file content against an import map. */
export function unmap(content: string, imports: record<string>, { logger: log = new Logger() } = {}): { result: string; resolved: number } {
  let resolved = 0
  const directories = Object.keys(imports).filter((module) => module.endsWith("/")) as string[]
  const result = content.replace(regex, function (match, statement, quote, module, i) {
    log.with({ i }).trace(match)
    let mapped = null as Nullable<string>
    if (module in imports) {
      mapped = imports[module]
    } else if (directories.some((directory) => module.startsWith(directory))) {
      const [directory] = directories.filter((directory) => module.startsWith(directory)).sort((a, b) => b.length - a.length)
      mapped = module.replace(directory, imports[directory])
    }
    if (typeof mapped === "string") {
      resolved++
      log.with({ i }).debug(`${module}${mapped}`)
      return `${statement}${mapped}${quote}`
    }
    return match
  })
  return { result, resolved }
}