6
6
* found in the LICENSE file at https://angular.io/license
7
7
*/
8
8
9
+ import { RawSourceMap } from '@ampproject/remapping' ;
10
+ import MagicString from 'magic-string' ;
9
11
import { Dirent , readFileSync , readdirSync } from 'node:fs' ;
10
12
import { basename , dirname , extname , join , relative } from 'node:path' ;
11
13
import { fileURLToPath , pathToFileURL } from 'node:url' ;
@@ -31,8 +33,13 @@ const URL_REGEXP = /url(?:\(\s*(['"]?))(.*?)(?:\1\s*\))/g;
31
33
abstract class UrlRebasingImporter implements Importer < 'sync' > {
32
34
/**
33
35
* @param entryDirectory The directory of the entry stylesheet that was passed to the Sass compiler.
36
+ * @param rebaseSourceMaps When provided, rebased files will have an intermediate sourcemap added to the Map
37
+ * which can be used to generate a final sourcemap that contains original sources.
34
38
*/
35
- constructor ( private entryDirectory : string ) { }
39
+ constructor (
40
+ private entryDirectory : string ,
41
+ private rebaseSourceMaps ?: Map < string , RawSourceMap > ,
42
+ ) { }
36
43
37
44
abstract canonicalize ( url : string , options : { fromImport : boolean } ) : URL | null ;
38
45
@@ -46,6 +53,7 @@ abstract class UrlRebasingImporter implements Importer<'sync'> {
46
53
47
54
let match ;
48
55
URL_REGEXP . lastIndex = 0 ;
56
+ let updatedContents ;
49
57
while ( ( match = URL_REGEXP . exec ( contents ) ) ) {
50
58
const originalUrl = match [ 2 ] ;
51
59
@@ -60,10 +68,21 @@ abstract class UrlRebasingImporter implements Importer<'sync'> {
60
68
// https://developer.mozilla.org/en-US/docs/Web/CSS/url#syntax
61
69
const rebasedUrl = './' + rebasedPath . replace ( / \\ / g, '/' ) . replace ( / [ ( ) \s ' " ] / g, '\\$&' ) ;
62
70
63
- contents =
64
- contents . slice ( 0 , match . index ) +
65
- `url(${ rebasedUrl } )` +
66
- contents . slice ( match . index + match [ 0 ] . length ) ;
71
+ updatedContents ??= new MagicString ( contents ) ;
72
+ updatedContents . update ( match . index , match . index + match [ 0 ] . length , `url(${ rebasedUrl } )` ) ;
73
+ }
74
+
75
+ if ( updatedContents ) {
76
+ contents = updatedContents . toString ( ) ;
77
+ if ( this . rebaseSourceMaps ) {
78
+ // Generate an intermediate source map for the rebasing changes
79
+ const map = updatedContents . generateMap ( {
80
+ hires : true ,
81
+ includeContent : true ,
82
+ source : canonicalUrl . href ,
83
+ } ) ;
84
+ this . rebaseSourceMaps . set ( canonicalUrl . href , map as RawSourceMap ) ;
85
+ }
67
86
}
68
87
}
69
88
@@ -94,8 +113,12 @@ abstract class UrlRebasingImporter implements Importer<'sync'> {
94
113
* the URLs in the output of the Sass compiler reflect the final filesystem location of the output CSS file.
95
114
*/
96
115
export class RelativeUrlRebasingImporter extends UrlRebasingImporter {
97
- constructor ( entryDirectory : string , private directoryCache = new Map < string , Dirent [ ] > ( ) ) {
98
- super ( entryDirectory ) ;
116
+ constructor (
117
+ entryDirectory : string ,
118
+ private directoryCache = new Map < string , Dirent [ ] > ( ) ,
119
+ rebaseSourceMaps ?: Map < string , RawSourceMap > ,
120
+ ) {
121
+ super ( entryDirectory , rebaseSourceMaps ) ;
99
122
}
100
123
101
124
canonicalize ( url : string , options : { fromImport : boolean } ) : URL | null {
@@ -238,9 +261,10 @@ export class ModuleUrlRebasingImporter extends RelativeUrlRebasingImporter {
238
261
constructor (
239
262
entryDirectory : string ,
240
263
directoryCache : Map < string , Dirent [ ] > ,
264
+ rebaseSourceMaps : Map < string , RawSourceMap > | undefined ,
241
265
private finder : FileImporter < 'sync' > [ 'findFileUrl' ] ,
242
266
) {
243
- super ( entryDirectory , directoryCache ) ;
267
+ super ( entryDirectory , directoryCache , rebaseSourceMaps ) ;
244
268
}
245
269
246
270
override canonicalize ( url : string , options : { fromImport : boolean } ) : URL | null {
@@ -263,9 +287,10 @@ export class LoadPathsUrlRebasingImporter extends RelativeUrlRebasingImporter {
263
287
constructor (
264
288
entryDirectory : string ,
265
289
directoryCache : Map < string , Dirent [ ] > ,
290
+ rebaseSourceMaps : Map < string , RawSourceMap > | undefined ,
266
291
private loadPaths : Iterable < string > ,
267
292
) {
268
- super ( entryDirectory , directoryCache ) ;
293
+ super ( entryDirectory , directoryCache , rebaseSourceMaps ) ;
269
294
}
270
295
271
296
override canonicalize ( url : string , options : { fromImport : boolean } ) : URL | null {
0 commit comments