@@ -25,6 +25,94 @@ const HOT_CSS_ROUTE = `${HOT_CSS_BASE_PATH}/${HOT_CSS_FILE_NAME}`;
2525const HOT_CSS_MAP_ROUTE = `${ HOT_CSS_BASE_PATH } /${ HOT_CSS_MAP_FILE_NAME } ` ;
2626const HOT_CSS_EVENTS_ROUTE = `${ HOT_CSS_BASE_PATH } /events` ;
2727
28+ function appendSourceMapComment ( cssContent , mapFileName ) {
29+ const normalizedCss = String ( cssContent || '' ) . replace ( / \/ \* # s o u r c e M a p p i n g U R L = .* ?\* \/ / g, '' ) . trimEnd ( ) ;
30+ const normalizedMapFile = String ( mapFileName || '' ) . trim ( ) ;
31+
32+ if ( normalizedMapFile === '' ) {
33+ return normalizedCss ;
34+ }
35+
36+ return `${ normalizedCss } \n/*# sourceMappingURL=${ normalizedMapFile } */\n` ;
37+ }
38+
39+ function normalizeSourceMapForDisplay ( mapContent , projectRootPath ) {
40+ if ( typeof mapContent !== 'string' || mapContent . trim ( ) === '' ) {
41+ return '' ;
42+ }
43+
44+ let parsedMap ;
45+ try {
46+ parsedMap = JSON . parse ( mapContent ) ;
47+ } catch ( _error ) {
48+ return mapContent ;
49+ }
50+
51+ if ( ! parsedMap || typeof parsedMap !== 'object' || ! Array . isArray ( parsedMap . sources ) ) {
52+ return mapContent ;
53+ }
54+
55+ parsedMap . sources = parsedMap . sources . map ( ( source ) => normalizeSourceMapSource ( source , projectRootPath ) ) ;
56+
57+ if ( typeof parsedMap . sourceRoot === 'string' && parsedMap . sourceRoot . startsWith ( 'file://' ) ) {
58+ parsedMap . sourceRoot = '' ;
59+ }
60+
61+ return JSON . stringify ( parsedMap ) ;
62+ }
63+
64+ function normalizeSourceMapSource ( source , projectRootPath ) {
65+ if ( typeof source !== 'string' || source === '' ) {
66+ return source ;
67+ }
68+
69+ const projectRoot = path . resolve ( projectRootPath ) ;
70+ const projectRootPrefix = `${ projectRoot } ${ path . sep } ` ;
71+
72+ if ( source . startsWith ( 'file://' ) ) {
73+ try {
74+ const absolutePath = path . resolve ( fileURLToPath ( source ) ) ;
75+ const normalizedAbsolute = absolutePath . replace ( / \\ / g, '/' ) ;
76+
77+ if ( normalizedAbsolute . startsWith ( '/var/www/html/' ) ) {
78+ return toRootAbsoluteDisplayPath ( normalizedAbsolute . slice ( '/var/www/html/' . length ) ) ;
79+ }
80+
81+ if ( absolutePath === projectRoot || absolutePath . startsWith ( projectRootPrefix ) ) {
82+ return toRootAbsoluteDisplayPath ( path . relative ( projectRoot , absolutePath ) . replace ( / \\ / g, '/' ) ) ;
83+ }
84+
85+ return normalizedAbsolute ;
86+ } catch ( _error ) {
87+ return source ;
88+ }
89+ }
90+
91+ if ( path . isAbsolute ( source ) ) {
92+ const absolutePath = path . resolve ( source ) ;
93+ if ( absolutePath === projectRoot || absolutePath . startsWith ( projectRootPrefix ) ) {
94+ return toRootAbsoluteDisplayPath ( path . relative ( projectRoot , absolutePath ) . replace ( / \\ / g, '/' ) ) ;
95+ }
96+ }
97+
98+ return toRootAbsoluteDisplayPath ( source ) ;
99+ }
100+
101+ function toRootAbsoluteDisplayPath ( pathValue ) {
102+ const normalizedPath = String ( pathValue || '' ) . replace ( / \\ / g, '/' ) ;
103+ if (
104+ normalizedPath === ''
105+ || normalizedPath . startsWith ( '/' )
106+ || normalizedPath . startsWith ( './' )
107+ || normalizedPath . startsWith ( '../' )
108+ || / ^ [ a - z A - Z ] [ a - z A - Z \d + \- . ] * : / . test ( normalizedPath )
109+ ) {
110+ return normalizedPath ;
111+ }
112+
113+ return `/${ normalizedPath } ` ;
114+ }
115+
28116function readJsonFile ( filePath , fallbackValue = null ) {
29117 try {
30118 return JSON . parse ( fs . readFileSync ( filePath , 'utf8' ) ) ;
@@ -485,10 +573,16 @@ function createScssSidecar(projectRoot) {
485573 const result = await compileSass ( compileEntryPath ) ;
486574
487575 await fs . promises . mkdir ( path . dirname ( cssOutputPath ) , { recursive : true } ) ;
488- await fs . promises . writeFile ( cssOutputPath , result . css || '' , 'utf8' ) ;
576+ const normalizedMap = normalizeSourceMapForDisplay ( result . map || '' , rootPath ) ;
577+
578+ let cssOutput = result . css || '' ;
579+ if ( scssSourceMapEnabled && normalizedMap !== '' ) {
580+ cssOutput = appendSourceMapComment ( cssOutput , HOT_CSS_MAP_FILE_NAME ) ;
581+ }
582+ await fs . promises . writeFile ( cssOutputPath , cssOutput , 'utf8' ) ;
489583
490- if ( scssSourceMapEnabled && typeof result . map === 'string' && result . map !== '' ) {
491- await fs . promises . writeFile ( cssMapOutputPath , result . map , 'utf8' ) ;
584+ if ( scssSourceMapEnabled && normalizedMap !== '' ) {
585+ await fs . promises . writeFile ( cssMapOutputPath , normalizedMap , 'utf8' ) ;
492586 } else if ( fs . existsSync ( cssMapOutputPath ) ) {
493587 await fs . promises . unlink ( cssMapOutputPath ) ;
494588 }
0 commit comments