| 291 | } |
| 292 | |
| 293 | function buildTimeImportMetaUrlPlugin(): Plugin { |
| 294 | const idMap: Record<string, number> = {} |
| 295 | let lastIndex = 0 |
| 296 | |
| 297 | const prefix = `__vite_buildTimeImportMetaUrl_` |
| 298 | const keepCommentRE = /\/\*\*\s*[#@]__KEEP__\s*\*\/\s*$/ |
| 299 | |
| 300 | return { |
| 301 | name: 'import-meta-current-dirname', |
| 302 | transform: { |
| 303 | filter: { |
| 304 | code: 'import.meta.url', |
| 305 | }, |
| 306 | async handler(code, id) { |
| 307 | const relativeId = path.relative(dirname, id).replaceAll('\\', '/') |
| 308 | // only replace import.meta.url in src/ |
| 309 | if (!relativeId.startsWith('src/')) return |
| 310 | |
| 311 | let index: number |
| 312 | if (idMap[id]) { |
| 313 | index = idMap[id] |
| 314 | } else { |
| 315 | index = idMap[id] = lastIndex |
| 316 | lastIndex++ |
| 317 | } |
| 318 | |
| 319 | await init |
| 320 | |
| 321 | const s = new MagicString(code) |
| 322 | const [imports] = parse(code) |
| 323 | for (const { t, ss, se } of imports) { |
| 324 | if ( |
| 325 | t === ImportType.ImportMeta && |
| 326 | code.slice(se, se + 4) === '.url' |
| 327 | ) { |
| 328 | // ignore import.meta.url with /** #__KEEP__ */ comment |
| 329 | if (keepCommentRE.test(code.slice(0, ss))) { |
| 330 | keepCommentRE.lastIndex = 0 |
| 331 | continue |
| 332 | } |
| 333 | |
| 334 | // import.meta.url |
| 335 | s.overwrite(ss, se + 4, `${prefix}${index}`) |
| 336 | } |
| 337 | } |
| 338 | return s.hasChanged() ? s.toString() : undefined |
| 339 | }, |
| 340 | }, |
| 341 | renderChunk(code, chunk, outputOptions) { |
| 342 | if (!code.includes(prefix)) return |
| 343 | |
| 344 | return code.replace( |
| 345 | /__vite_buildTimeImportMetaUrl_(\d+)/g, |
| 346 | (_, index) => { |
| 347 | const originalFile = Object.keys(idMap).find( |
| 348 | (key) => idMap[key] === +index, |
| 349 | ) |
| 350 | if (!originalFile) { |