From 5b169d7b3b6eac45c4de0f653d181734c35437c8 Mon Sep 17 00:00:00 2001 From: MeAkib Date: Fri, 23 Oct 2026 18:38:24 +0600 Subject: [PATCH 1/3] fix(@schematics/angular): ignore non-workspace stylesheet entries when adding Tailwind The tailwind schematic selects the first `styles` entry ending in `.css` and appends the Tailwind import to it without checking that the entry is a file in the workspace. When the first `.css` entry is a package specifier such as `@angular/material/prebuilt-themes/azure-blue.css`, `ng add tailwindcss` fails with a file-does-not-exist exception, and when it is a path within `node_modules`, the vendor stylesheet is modified instead of a project file. Only consider entries that exist in the workspace and are not within `node_modules`, falling back to creating a dedicated `tailwind.css` otherwise. New specs reproduce both failures without this change. --- packages/schematics/angular/tailwind/index.ts | 4 +- .../schematics/angular/tailwind/index_spec.ts | 37 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/packages/schematics/angular/tailwind/index.ts b/packages/schematics/angular/tailwind/index.ts index 018f0f3b9f95..d32a014c03c5 100644 --- a/packages/schematics/angular/tailwind/index.ts +++ b/packages/schematics/angular/tailwind/index.ts @@ -48,9 +48,11 @@ function addTailwindStyles(options: { project: string }, project: ProjectDefinit let stylesheetPath: string | undefined; if (styles) { + // Only consider workspace source files. Entries such as package specifiers + // (`@angular/material/prebuilt-themes/...`) or files within `node_modules` must not be modified. stylesheetPath = styles .map((s) => (typeof s === 'string' ? s : s.input)) - .find((p) => p.endsWith('.css')); + .find((p) => p.endsWith('.css') && !p.startsWith('node_modules/') && tree.exists(p)); } if (!stylesheetPath) { diff --git a/packages/schematics/angular/tailwind/index_spec.ts b/packages/schematics/angular/tailwind/index_spec.ts index a70c3b3eef8d..31fdf15110c6 100644 --- a/packages/schematics/angular/tailwind/index_spec.ts +++ b/packages/schematics/angular/tailwind/index_spec.ts @@ -129,4 +129,41 @@ describe('Tailwind Schematic', () => { expect(tree.exists('/projects/bar/.postcssrc.json')).toBe(false); }); }); + + describe('with non-workspace stylesheets', () => { + function setStyles(tree: UnitTestTree, styles: string[]): void { + const workspace = getWorkspace(tree); + workspace.projects.bar.architect.build.options.styles = styles; + tree.overwrite('/angular.json', JSON.stringify(workspace, null, 2)); + } + + it('should create a tailwind stylesheet when the only CSS entry is a package theme', async () => { + appTree = await createTestApp(schematicRunner, appOptions, Style.Scss); + setStyles(appTree, [ + '@angular/material/prebuilt-themes/azure-blue.css', + 'projects/bar/src/styles.scss', + ]); + + const tree = await schematicRunner.runSchematic('tailwind', { project: 'bar' }, appTree); + + expect(tree.exists('/projects/bar/src/tailwind.css')).toBe(true); + const workspace = getWorkspace(tree); + expect(workspace.projects.bar.architect.build.options.styles).toEqual([ + 'projects/bar/src/tailwind.css', + '@angular/material/prebuilt-themes/azure-blue.css', + 'projects/bar/src/styles.scss', + ]); + }); + + it('should not modify a stylesheet inside node_modules', async () => { + const vendorStylesheet = 'node_modules/bootstrap/dist/css/bootstrap.min.css'; + appTree.create(`/${vendorStylesheet}`, 'body { margin: 0; }'); + setStyles(appTree, [vendorStylesheet, 'projects/bar/src/styles.css']); + + const tree = await schematicRunner.runSchematic('tailwind', { project: 'bar' }, appTree); + + expect(tree.readContent(`/${vendorStylesheet}`)).not.toContain('tailwindcss'); + expect(tree.readContent('/projects/bar/src/styles.css')).toContain(`@import 'tailwindcss';`); + }); + }); }); From 6b6a8cf21af98b823dec88c0c14c55b381a77b0c Mon Sep 17 00:00:00 2001 From: Shuaib Hasan Akib <48770016+MeAkib@users.noreply.github.com> Date: Fri, 23 Oct 2026 23:20:46 +0600 Subject: [PATCH 2/3] fixup! 5b169d7b3b6eac45c4de0f653d181734c35437c8 Co-authored-by: Alan Agius --- packages/schematics/angular/tailwind/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/schematics/angular/tailwind/index.ts b/packages/schematics/angular/tailwind/index.ts index d32a014c03c5..540b38310178 100644 --- a/packages/schematics/angular/tailwind/index.ts +++ b/packages/schematics/angular/tailwind/index.ts @@ -52,7 +52,7 @@ function addTailwindStyles(options: { project: string }, project: ProjectDefinit // (`@angular/material/prebuilt-themes/...`) or files within `node_modules` must not be modified. stylesheetPath = styles .map((s) => (typeof s === 'string' ? s : s.input)) - .find((p) => p.endsWith('.css') && !p.startsWith('node_modules/') && tree.exists(p)); + .find((p) => p.endsWith('.css') && !/(?:^|\/)node_modules\//.test(p) && tree.exists(p)); } if (!stylesheetPath) { From 9b9cda4b8b071539f56642c3fd723258186792a4 Mon Sep 17 00:00:00 2001 From: MeAkib Date: Fri, 23 Oct 2026 23:23:14 +0600 Subject: [PATCH 3/3] fixup! fix(@schematics/angular): ignore non-workspace stylesheet entries when adding Tailwind --- packages/schematics/angular/tailwind/index_spec.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/schematics/angular/tailwind/index_spec.ts b/packages/schematics/angular/tailwind/index_spec.ts index 31fdf15110c6..b55d76fff385 100644 --- a/packages/schematics/angular/tailwind/index_spec.ts +++ b/packages/schematics/angular/tailwind/index_spec.ts @@ -138,7 +138,6 @@ describe('Tailwind Schematic', () => { } it('should create a tailwind stylesheet when the only CSS entry is a package theme', async () => { - appTree = await createTestApp(schematicRunner, appOptions, Style.Scss); setStyles(appTree, [ '@angular/material/prebuilt-themes/azure-blue.css', 'projects/bar/src/styles.scss',