| import path from 'node:path'; | |
| const IS_WINDOWS = process.platform === 'win32'; | |
| /** | |
| * @typedef {{ | |
| * file?: string; | |
| * sources?: string[]; | |
| * sourceRoot?: string; | |
| * }} SourceMapFileRefs | |
| */ | |
| /** | |
| * convert absolute paths in sourcemap file refs to their relative equivalents to avoid leaking fs info | |
| * | |
| * map is modified in place. | |
| * | |
| * @param {SourceMapFileRefs | undefined} map sourcemap | |
| * @param {string} filename absolute path to file the sourcemap is for | |
| */ | |
| export function mapToRelative(map, filename) { | |
| if (!map) { | |
| return; | |
| } | |
| const sourceRoot = map.sourceRoot; | |
| const dirname = path.dirname(filename); | |
| /** @type {(s: string) => string} */ | |
| const toRelative = (s) => { | |
| if (!s) { | |
| return s; | |
| } | |
| /** @type {string} */ | |
| let sourcePath; | |
| if (s.startsWith('file:///')) { | |
| // windows has file:///C:/foo and posix has file:///foo, so we have to remove one extra on windows | |
| sourcePath = s.slice(IS_WINDOWS ? 8 : 7); | |
| } else if (sourceRoot) { | |
| const sep = sourceRoot[sourceRoot.length - 1] === '/' || s[0] === '/' ? '' : '/'; | |
| sourcePath = `${sourceRoot}${sep}${s}`; | |
| } else { | |
| sourcePath = s; | |
| } | |
| return path.isAbsolute(sourcePath) ? path.relative(dirname, sourcePath) : sourcePath; | |
| }; | |
| if (map.file) { | |
| map.file = path.basename(filename); | |
| } | |
| if (map.sources) { | |
| map.sources = map.sources.map(toRelative); | |
| } | |
| if (map.sourceRoot) { | |
| // we have prepended sourceRoot and computed relative paths from it | |
| // remove it here to avoid downstream processing prepending it again | |
| delete map.sourceRoot; | |
| } | |
| } | |
| /** | |
| * vitePreprocess uses an extra lang extension to tell vite about the type of preprocessor to use | |
| * This function removes it afterwards to get back working file refs | |
| * | |
| * map is modified in place. | |
| * | |
| * @param {SourceMapFileRefs | undefined} map the output sourcemap | |
| * @param {string} suffix the suffix to remove | |
| */ | |
| export function removeLangSuffix(map, suffix) { | |
| if (!map) { | |
| return; | |
| } | |
| /** @type {(s:string)=> string} */ | |
| const removeSuffix = (s) => (s?.endsWith(suffix) ? s.slice(0, -1 * suffix.length) : s); | |
| if (map.file) { | |
| map.file = removeSuffix(map.file); | |
| } | |
| if (map.sources) { | |
| map.sources = map.sources.map(removeSuffix); | |
| } | |
| } | |