diff --git a/packages/angular/build/src/tools/esbuild/stylesheets/sass-language.ts b/packages/angular/build/src/tools/esbuild/stylesheets/sass-language.ts index c0fb7c7397fb..313b7ccaa662 100644 --- a/packages/angular/build/src/tools/esbuild/stylesheets/sass-language.ts +++ b/packages/angular/build/src/tools/esbuild/stylesheets/sass-language.ts @@ -174,6 +174,11 @@ async function compileString( if (isSassException(error)) { const fileWithError = error.span.url ? fileURLToPath(error.span.url) : undefined; + const watchFiles = [filePath, ...extractFilesFromStack(error.sassStack)]; + if (fileWithError) { + watchFiles.push(fileWithError); + } + return { loader: 'css', errors: [ @@ -182,7 +187,7 @@ async function compileString( }, ], warnings, - watchFiles: fileWithError ? [filePath, fileWithError] : [filePath], + watchFiles, }; } @@ -202,3 +207,29 @@ function sourceMapToUrlComment( return `/*# sourceMappingURL=data:application/json;charset=utf-8;base64,${urlSourceMap} */`; } + +function* extractFilesFromStack(stack: string): Iterable { + const lines = stack.split('\n'); + const cwd = process.cwd(); + + // Stack line has format of " " + for (const line of lines) { + const segments = line.split(' '); + if (segments.length < 3) { + break; + } + + // Extract path from stack line. + // Paths may contain spaces. All segments before location are part of the file path. + let path = ''; + let index = 0; + while (!segments[index].match(/\d+:\d+/)) { + path += segments[index++]; + } + + if (path) { + // Stack paths from dart-sass are relative to the current working directory (not input file or workspace root) + yield join(cwd, path); + } + } +}