Skip to content

Commit 5144aa7

Browse files
devversionmmalerba
authored andcommitted
feat(ng-add): respect project default style extension (#12618)
* feat(ng-add): respect project default style extension * No longer ignores the projects default style extension that has been specified in the `ng new` command (e.g. `new new test --style scss`) * Address feedback
1 parent 6732414 commit 5144aa7

File tree

12 files changed

+97
-42
lines changed

12 files changed

+97
-42
lines changed

src/lib/schematics/address-form/schema.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@
5858
},
5959
"styleext": {
6060
"description": "The file extension to be used for style files.",
61-
"type": "string",
62-
"default": "css"
61+
"type": "string"
6362
},
6463
"spec": {
6564
"type": "boolean",

src/lib/schematics/dashboard/index.spec.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,18 @@ import {Schema} from './schema';
55

66
describe('material-dashboard-schematic', () => {
77
let runner: SchematicTestRunner;
8-
const options: Schema = {
8+
9+
const baseOptions: Schema = {
910
name: 'foo',
1011
project: 'material',
11-
changeDetection: 'Default',
12-
styleext: 'css',
13-
spec: true,
14-
export: false,
1512
};
1613

1714
beforeEach(() => {
1815
runner = new SchematicTestRunner('schematics', collectionPath);
1916
});
2017

2118
it('should create dashboard files and add them to module', () => {
22-
const tree = runner.runSchematic('dashboard', { ...options }, createTestApp());
19+
const tree = runner.runSchematic('dashboard', baseOptions, createTestApp());
2320
const files = tree.files;
2421

2522
expect(files).toContain('/projects/material/src/app/foo/foo.component.css');
@@ -33,7 +30,7 @@ describe('material-dashboard-schematic', () => {
3330
});
3431

3532
it('should add dashboard imports to module', () => {
36-
const tree = runner.runSchematic('dashboard', { ...options }, createTestApp());
33+
const tree = runner.runSchematic('dashboard', baseOptions, createTestApp());
3734
const moduleContent = getFileContent(tree, '/projects/material/src/app/app.module.ts');
3835

3936
expect(moduleContent).toContain('MatGridListModule');
@@ -47,4 +44,17 @@ describe('material-dashboard-schematic', () => {
4744
`import { MatGridListModule, MatCardModule, MatMenuModule, MatIconModule, MatButtonModule } from '@angular/material';`);
4845
});
4946

47+
it('should support passing the style extension option', () => {
48+
const tree = runner.runSchematic(
49+
'dashboard', {styleext: 'scss', ...baseOptions}, createTestApp());
50+
51+
expect(tree.files).toContain('/projects/material/src/app/foo/foo.component.scss');
52+
});
53+
54+
it('should fallback to the default angular:component style extension', () => {
55+
const tree = runner.runSchematic('dashboard', baseOptions, createTestApp({style: 'less'}));
56+
57+
expect(tree.files).toContain('/projects/material/src/app/foo/foo.component.less');
58+
});
59+
5060
});

src/lib/schematics/dashboard/schema.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@
5858
},
5959
"styleext": {
6060
"description": "The file extension to be used for style files.",
61-
"type": "string",
62-
"default": "css"
61+
"type": "string"
6362
},
6463
"spec": {
6564
"type": "boolean",

src/lib/schematics/install/index.spec.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@ describe('material-install-schematic', () => {
4141
'./node_modules/@angular/material/prebuilt-themes/indigo-pink.css');
4242
});
4343

44-
it('should add custom theme', () => {
44+
it('should support adding a custom theme', () => {
45+
// TODO(devversion): currently a "custom" theme does only work for projects using SCSS.
46+
// TODO(devversion): Throw an error if a custom theme is being installed in a CSS project.
47+
appTree = createTestApp({style: 'scss'});
48+
4549
const tree = runner.runSchematic('ng-add', {theme: 'custom'}, appTree);
4650

4751
const workspace = getWorkspace(tree);

src/lib/schematics/nav/index.spec.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,17 @@ import {collectionPath, createTestApp} from '../test-setup/test-app';
66
describe('material-nav-schematic', () => {
77
let runner: SchematicTestRunner;
88

9-
const options: Schema = {
9+
const baseOptions: Schema = {
1010
name: 'foo',
1111
project: 'material',
12-
changeDetection: 'Default',
13-
styleext: 'css',
14-
spec: true,
15-
export: false,
1612
};
1713

1814
beforeEach(() => {
1915
runner = new SchematicTestRunner('schematics', collectionPath);
2016
});
2117

2218
it('should create nav files and add them to module', () => {
23-
const tree = runner.runSchematic('nav', { ...options }, createTestApp());
19+
const tree = runner.runSchematic('nav', baseOptions, createTestApp());
2420
const files = tree.files;
2521

2622
expect(files).toContain('/projects/material/src/app/foo/foo.component.css');
@@ -34,7 +30,7 @@ describe('material-nav-schematic', () => {
3430
});
3531

3632
it('should add nav imports to module', () => {
37-
const tree = runner.runSchematic('nav', { ...options }, createTestApp());
33+
const tree = runner.runSchematic('nav', baseOptions, createTestApp());
3834
const moduleContent = getFileContent(tree, '/projects/material/src/app/app.module.ts');
3935

4036
expect(moduleContent).toContain('LayoutModule');
@@ -50,4 +46,15 @@ describe('material-nav-schematic', () => {
5046
`MatListModule } from '@angular/material';`);
5147
});
5248

49+
it('should support passing the style extension option', () => {
50+
const tree = runner.runSchematic('nav', {styleext: 'scss', ...baseOptions}, createTestApp());
51+
52+
expect(tree.files).toContain('/projects/material/src/app/foo/foo.component.scss');
53+
});
54+
55+
it('should fallback to the default angular:component style extension', () => {
56+
const tree = runner.runSchematic('nav', baseOptions, createTestApp({style: 'less'}));
57+
58+
expect(tree.files).toContain('/projects/material/src/app/foo/foo.component.less');
59+
});
5360
});

src/lib/schematics/nav/schema.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@
5858
},
5959
"styleext": {
6060
"description": "The file extension to be used for style files.",
61-
"type": "string",
62-
"default": "css"
61+
"type": "string"
6362
},
6463
"spec": {
6564
"type": "boolean",

src/lib/schematics/table/index.spec.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,17 @@ import {collectionPath, createTestApp} from '../test-setup/test-app';
66
describe('material-table-schematic', () => {
77
let runner: SchematicTestRunner;
88

9-
const options: Schema = {
9+
const baseOptions: Schema = {
1010
name: 'foo',
1111
project: 'material',
12-
changeDetection: 'Default',
13-
styleext: 'css',
14-
spec: true,
15-
export: false,
1612
};
1713

1814
beforeEach(() => {
1915
runner = new SchematicTestRunner('schematics', collectionPath);
2016
});
2117

2218
it('should create table files and add them to module', () => {
23-
const tree = runner.runSchematic('table', { ...options }, createTestApp());
19+
const tree = runner.runSchematic('table', baseOptions, createTestApp());
2420
const files = tree.files;
2521

2622
expect(files).toContain('/projects/material/src/app/foo/foo.component.css');
@@ -45,8 +41,20 @@ describe('material-table-schematic', () => {
4541
expect(componentContent).toContain('FooDataSource');
4642
});
4743

44+
it('should support passing the style extension option', () => {
45+
const tree = runner.runSchematic('table', {styleext: 'scss', ...baseOptions}, createTestApp());
46+
47+
expect(tree.files).toContain('/projects/material/src/app/foo/foo.component.scss');
48+
});
49+
50+
it('should fallback to the default angular:component style extension', () => {
51+
const tree = runner.runSchematic('table', baseOptions, createTestApp({style: 'less'}));
52+
53+
expect(tree.files).toContain('/projects/material/src/app/foo/foo.component.less');
54+
});
55+
4856
it('should add table imports to module', () => {
49-
const tree = runner.runSchematic('table', { ...options }, createTestApp());
57+
const tree = runner.runSchematic('table', baseOptions, createTestApp());
5058
const moduleContent = getFileContent(tree, '/projects/material/src/app/app.module.ts');
5159

5260
expect(moduleContent).toContain('MatTableModule');

src/lib/schematics/table/schema.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@
5858
},
5959
"styleext": {
6060
"description": "The file extension to be used for style files.",
61-
"type": "string",
62-
"default": "css"
61+
"type": "string"
6362
},
6463
"spec": {
6564
"type": "boolean",

src/lib/schematics/test-setup/test-app.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export const collectionPath = join(__dirname, '..', 'collection.json');
1616
export const migrationCollection = join(__dirname, '..', 'migration.json');
1717

1818
/** Create a base app used for testing. */
19-
export function createTestApp(): UnitTestTree {
19+
export function createTestApp(appOptions = {}): UnitTestTree {
2020
const baseRunner = new SchematicTestRunner('material-schematics', collectionPath);
2121

2222
const workspaceTree = baseRunner.runExternalSchematic('@schematics/angular', 'workspace', {
@@ -25,12 +25,6 @@ export function createTestApp(): UnitTestTree {
2525
newProjectRoot: 'projects',
2626
});
2727

28-
return baseRunner.runExternalSchematic('@schematics/angular', 'application', {
29-
name: 'material',
30-
inlineStyle: false,
31-
inlineTemplate: false,
32-
routing: false,
33-
style: 'scss',
34-
skipTests: false,
35-
}, workspaceTree);
28+
return baseRunner.runExternalSchematic('@schematics/angular', 'application',
29+
{...appOptions, name: 'material'}, workspaceTree);
3630
}

src/lib/schematics/tree/schema.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@
5858
},
5959
"styleext": {
6060
"description": "The file extension to be used for style files.",
61-
"type": "string",
62-
"default": "css"
61+
"type": "string"
6362
},
6463
"spec": {
6564
"type": "boolean",

src/lib/schematics/utils/build-component.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import {validateHtmlSelector, validateName} from '@schematics/angular/utility/va
3939
import {resolve, dirname, join} from 'path';
4040
import {readFileSync} from 'fs';
4141
import * as ts from 'typescript';
42+
import {determineDefaultStyleExt} from './default-style-ext';
4243

4344
function readIntoSourceFile(host: Tree, modulePath: string): ts.SourceFile {
4445
const text = host.read(modulePath);
@@ -137,7 +138,7 @@ function buildSelector(options: ComponentOptions, projectPrefix: string) {
137138
*/
138139
function indentTextContent(text: string, numSpaces: number): string {
139140
// In the Material project there should be only LF line-endings, but the schematic files
140-
// are not being linted and therefore there can be also use CRLF or just CR line-endings.
141+
// are not being linted and therefore there can be also CRLF or just CR line-endings.
141142
return text.replace(/(\r\n|\r|\n)/g, `$1${' '.repeat(numSpaces)}`);
142143
}
143144

@@ -160,13 +161,18 @@ export function buildComponent(options: ComponentOptions,
160161
const schematicFilesPath = resolve(dirname(context.schematic.description.path),
161162
schematicFilesUrl);
162163

164+
if (!options.styleext) {
165+
options.styleext = determineDefaultStyleExt(project);
166+
}
167+
163168
if (options.path === undefined) {
164169
options.path = buildDefaultPath(project);
165170
}
166171

167172
options.module = findModuleFromOptions(host, options);
168173

169174
const parsedPath = parseName(options.path, options.name);
175+
170176
options.name = parsedPath.name;
171177
options.path = parsedPath.path;
172178
options.selector = options.selector || buildSelector(options, project.prefix);
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {WorkspaceProject} from '@schematics/angular/utility/config';
10+
11+
/**
12+
* Style extension that will be used if no default style extension for the CLI project
13+
* could be determined.
14+
*/
15+
const fallbackStyleExtension = 'css';
16+
17+
/**
18+
* Determines the default style extension in the Angular CLI project by looking for the default
19+
* component schematic options. This is necessary for now because when creating CLI projects,
20+
* the CLI only makes the default `--style` option available for the `angular:component` schematic.
21+
*/
22+
export function determineDefaultStyleExt(project: WorkspaceProject): string | null {
23+
if (project.schematics &&
24+
project.schematics['@schematics/angular:component'] &&
25+
project.schematics['@schematics/angular:component']['styleext']) {
26+
27+
return project.schematics['@schematics/angular:component']['styleext'];
28+
}
29+
30+
return fallbackStyleExtension;
31+
}

0 commit comments

Comments
 (0)