diff --git a/src/lib/schematics/address-form/index.ts b/src/lib/schematics/address-form/index.ts index 9d27dce05b5..06626425066 100644 --- a/src/lib/schematics/address-form/index.ts +++ b/src/lib/schematics/address-form/index.ts @@ -18,10 +18,8 @@ import {addModuleImportToModule, findModuleFromOptions} from '../utils/ast'; export default function(options: Schema): Rule { return chain([ buildComponent({...options}, { - template: options.inlineTemplate && - './__path__/__name@dasherize@if-flat__/__name@dasherize__.component.html', - stylesheet: options.inlineStyle && - './__path__/__name@dasherize@if-flat__/__name@dasherize__.component.__styleext__', + template: './__path__/__name@dasherize@if-flat__/__name@dasherize__.component.html', + stylesheet: './__path__/__name@dasherize@if-flat__/__name@dasherize__.component.__styleext__', }), options.skipImport ? noop() : addFormModulesToModule(options) ]); diff --git a/src/lib/schematics/address-form/schema.json b/src/lib/schematics/address-form/schema.json index c0e9f3b2b32..7aa223fad8f 100644 --- a/src/lib/schematics/address-form/schema.json +++ b/src/lib/schematics/address-form/schema.json @@ -28,13 +28,11 @@ "inlineStyle": { "description": "Specifies if the style will be in the ts file.", "type": "boolean", - "default": false, "alias": "s" }, "inlineTemplate": { "description": "Specifies if the template will be in the ts file.", "type": "boolean", - "default": false, "alias": "t" }, "viewEncapsulation": { @@ -62,8 +60,7 @@ }, "spec": { "type": "boolean", - "description": "Specifies if a spec file is generated.", - "default": true + "description": "Specifies if a spec file is generated." }, "flat": { "type": "boolean", diff --git a/src/lib/schematics/dashboard/index.spec.ts b/src/lib/schematics/dashboard/index.spec.ts index 7fb9a1b4f4e..112dfb99f06 100644 --- a/src/lib/schematics/dashboard/index.spec.ts +++ b/src/lib/schematics/dashboard/index.spec.ts @@ -44,17 +44,65 @@ describe('material-dashboard-schematic', () => { `import { MatGridListModule, MatCardModule, MatMenuModule, MatIconModule, MatButtonModule } from '@angular/material';`); }); - it('should support passing the style extension option', () => { - const tree = runner.runSchematic( - 'dashboard', {styleext: 'scss', ...baseOptions}, createTestApp()); + describe('styleext option', () => { + it('should respect the option value', () => { + const tree = runner.runSchematic( + 'dashboard', {styleext: 'scss', ...baseOptions}, createTestApp()); - expect(tree.files).toContain('/projects/material/src/app/foo/foo.component.scss'); + expect(tree.files).toContain('/projects/material/src/app/foo/foo.component.scss'); + }); + + it('should fallback to the @schematics/angular:component option value', () => { + const tree = runner.runSchematic('dashboard', baseOptions, createTestApp({style: 'less'})); + + expect(tree.files).toContain('/projects/material/src/app/foo/foo.component.less'); + }); }); - it('should fallback to the default angular:component style extension', () => { - const tree = runner.runSchematic('dashboard', baseOptions, createTestApp({style: 'less'})); + describe('inlineStyle option', () => { + it('should respect the option value', () => { + const tree = runner.runSchematic( + 'dashboard', {inlineStyle: true, ...baseOptions}, createTestApp()); - expect(tree.files).toContain('/projects/material/src/app/foo/foo.component.less'); + expect(tree.files).not.toContain('/projects/material/src/app/foo/foo.component.css'); + }); + + it('should fallback to the @schematics/angular:component option value', () => { + const tree = runner.runSchematic( + 'dashboard', baseOptions, createTestApp({inlineStyle: true})); + + expect(tree.files).not.toContain('/projects/material/src/app/foo/foo.component.css'); + }); }); + describe('inlineTemplate option', () => { + it('should respect the option value', () => { + const tree = runner.runSchematic( + 'dashboard', {inlineTemplate: true, ...baseOptions}, createTestApp()); + + expect(tree.files).not.toContain('/projects/material/src/app/foo/foo.component.html'); + }); + + it('should fallback to the @schematics/angular:component option value', () => { + const tree = runner.runSchematic( + 'dashboard', baseOptions, createTestApp({inlineTemplate: true})); + + expect(tree.files).not.toContain('/projects/material/src/app/foo/foo.component.html'); + }); + }); + + describe('spec option', () => { + it('should respect the option value', () => { + const tree = runner.runSchematic( + 'dashboard', {spec: false, ...baseOptions}, createTestApp()); + + expect(tree.files).not.toContain('/projects/material/src/app/foo/foo.component.spec.ts'); + }); + + it('should fallback to the @schematics/angular:component option value', () => { + const tree = runner.runSchematic('dashboard', baseOptions, createTestApp({skipTests: true})); + + expect(tree.files).not.toContain('/projects/material/src/app/foo/foo.component.spec.ts'); + }); + }); }); diff --git a/src/lib/schematics/dashboard/index.ts b/src/lib/schematics/dashboard/index.ts index ef02e6e3003..0c4366781df 100644 --- a/src/lib/schematics/dashboard/index.ts +++ b/src/lib/schematics/dashboard/index.ts @@ -18,10 +18,8 @@ import {Schema} from './schema'; export default function(options: Schema): Rule { return chain([ buildComponent({...options}, { - template: options.inlineTemplate && - './__path__/__name@dasherize@if-flat__/__name@dasherize__.component.html', - stylesheet: options.inlineStyle && - './__path__/__name@dasherize@if-flat__/__name@dasherize__.component.__styleext__', + template: './__path__/__name@dasherize@if-flat__/__name@dasherize__.component.html', + stylesheet: './__path__/__name@dasherize@if-flat__/__name@dasherize__.component.__styleext__', }), options.skipImport ? noop() : addNavModulesToModule(options) ]); diff --git a/src/lib/schematics/dashboard/schema.json b/src/lib/schematics/dashboard/schema.json index 28d3b0be9c0..0c833b046f1 100644 --- a/src/lib/schematics/dashboard/schema.json +++ b/src/lib/schematics/dashboard/schema.json @@ -28,13 +28,11 @@ "inlineStyle": { "description": "Specifies if the style will be in the ts file.", "type": "boolean", - "default": false, "alias": "s" }, "inlineTemplate": { "description": "Specifies if the template will be in the ts file.", "type": "boolean", - "default": false, "alias": "t" }, "viewEncapsulation": { @@ -62,8 +60,7 @@ }, "spec": { "type": "boolean", - "description": "Specifies if a spec file is generated.", - "default": true + "description": "Specifies if a spec file is generated." }, "flat": { "type": "boolean", diff --git a/src/lib/schematics/nav/index.spec.ts b/src/lib/schematics/nav/index.spec.ts index bc2b2315544..9c93f7838ff 100644 --- a/src/lib/schematics/nav/index.spec.ts +++ b/src/lib/schematics/nav/index.spec.ts @@ -46,15 +46,61 @@ describe('material-nav-schematic', () => { `MatListModule } from '@angular/material';`); }); - it('should support passing the style extension option', () => { - const tree = runner.runSchematic('nav', {styleext: 'scss', ...baseOptions}, createTestApp()); + describe('styleext option', () => { + it('should respect the option value', () => { + const tree = runner.runSchematic('nav', {styleext: 'scss', ...baseOptions}, createTestApp()); - expect(tree.files).toContain('/projects/material/src/app/foo/foo.component.scss'); + expect(tree.files).toContain('/projects/material/src/app/foo/foo.component.scss'); + }); + + it('should fallback to the @schematics/angular:component option value', () => { + const tree = runner.runSchematic('nav', baseOptions, createTestApp({style: 'less'})); + + expect(tree.files).toContain('/projects/material/src/app/foo/foo.component.less'); + }); }); - it('should fallback to the default angular:component style extension', () => { - const tree = runner.runSchematic('nav', baseOptions, createTestApp({style: 'less'})); + describe('inlineStyle option', () => { + it('should respect the option value', () => { + const tree = runner.runSchematic( + 'nav', {inlineStyle: true, ...baseOptions}, createTestApp()); - expect(tree.files).toContain('/projects/material/src/app/foo/foo.component.less'); + expect(tree.files).not.toContain('/projects/material/src/app/foo/foo.component.css'); + }); + + it('should fallback to the @schematics/angular:component option value', () => { + const tree = runner.runSchematic('nav', baseOptions, createTestApp({inlineStyle: true})); + + expect(tree.files).not.toContain('/projects/material/src/app/foo/foo.component.css'); + }); + }); + + describe('inlineTemplate option', () => { + it('should respect the option value', () => { + const tree = runner.runSchematic( + 'nav', {inlineTemplate: true, ...baseOptions}, createTestApp()); + + expect(tree.files).not.toContain('/projects/material/src/app/foo/foo.component.html'); + }); + + it('should fallback to the @schematics/angular:component option value', () => { + const tree = runner.runSchematic('nav', baseOptions, createTestApp({inlineTemplate: true})); + + expect(tree.files).not.toContain('/projects/material/src/app/foo/foo.component.html'); + }); + }); + + describe('spec option', () => { + it('should respect the option value', () => { + const tree = runner.runSchematic('nav', {spec: false, ...baseOptions}, createTestApp()); + + expect(tree.files).not.toContain('/projects/material/src/app/foo/foo.component.spec.ts'); + }); + + it('should fallback to the @schematics/angular:component option value', () => { + const tree = runner.runSchematic('nav', baseOptions, createTestApp({skipTests: true})); + + expect(tree.files).not.toContain('/projects/material/src/app/foo/foo.component.spec.ts'); + }); }); }); diff --git a/src/lib/schematics/nav/index.ts b/src/lib/schematics/nav/index.ts index 90b897d0cce..e25d949a0f9 100644 --- a/src/lib/schematics/nav/index.ts +++ b/src/lib/schematics/nav/index.ts @@ -18,10 +18,8 @@ import {addModuleImportToModule, findModuleFromOptions} from '../utils/ast'; export default function(options: Schema): Rule { return chain([ buildComponent({...options}, { - template: options.inlineTemplate && - './__path__/__name@dasherize@if-flat__/__name@dasherize__.component.html', - stylesheet: options.inlineStyle && - './__path__/__name@dasherize@if-flat__/__name@dasherize__.component.__styleext__', + template: './__path__/__name@dasherize@if-flat__/__name@dasherize__.component.html', + stylesheet: './__path__/__name@dasherize@if-flat__/__name@dasherize__.component.__styleext__', }), options.skipImport ? noop() : addNavModulesToModule(options) ]); diff --git a/src/lib/schematics/nav/schema.json b/src/lib/schematics/nav/schema.json index db3c7423a11..89afc4bf117 100644 --- a/src/lib/schematics/nav/schema.json +++ b/src/lib/schematics/nav/schema.json @@ -28,13 +28,11 @@ "inlineStyle": { "description": "Specifies if the style will be in the ts file.", "type": "boolean", - "default": false, "alias": "s" }, "inlineTemplate": { "description": "Specifies if the template will be in the ts file.", "type": "boolean", - "default": false, "alias": "t" }, "viewEncapsulation": { @@ -62,8 +60,7 @@ }, "spec": { "type": "boolean", - "description": "Specifies if a spec file is generated.", - "default": true + "description": "Specifies if a spec file is generated." }, "flat": { "type": "boolean", diff --git a/src/lib/schematics/table/index.spec.ts b/src/lib/schematics/table/index.spec.ts index 317ccb25794..c7250b34f9a 100644 --- a/src/lib/schematics/table/index.spec.ts +++ b/src/lib/schematics/table/index.spec.ts @@ -41,18 +41,6 @@ describe('material-table-schematic', () => { expect(componentContent).toContain('FooDataSource'); }); - it('should support passing the style extension option', () => { - const tree = runner.runSchematic('table', {styleext: 'scss', ...baseOptions}, createTestApp()); - - expect(tree.files).toContain('/projects/material/src/app/foo/foo.component.scss'); - }); - - it('should fallback to the default angular:component style extension', () => { - const tree = runner.runSchematic('table', baseOptions, createTestApp({style: 'less'})); - - expect(tree.files).toContain('/projects/material/src/app/foo/foo.component.less'); - }); - it('should add table imports to module', () => { const tree = runner.runSchematic('table', baseOptions, createTestApp()); const moduleContent = getFileContent(tree, '/projects/material/src/app/app.module.ts'); @@ -65,4 +53,63 @@ describe('material-table-schematic', () => { `import { MatTableModule, MatPaginatorModule, MatSortModule } from '@angular/material';`); }); + describe('styleext option', () => { + it('should respect the option value', () => { + const tree = runner.runSchematic( + 'table', {styleext: 'scss', ...baseOptions}, createTestApp()); + + expect(tree.files).toContain('/projects/material/src/app/foo/foo.component.scss'); + }); + + it('should fallback to the @schematics/angular:component option value', () => { + const tree = runner.runSchematic('table', baseOptions, createTestApp({style: 'less'})); + + expect(tree.files).toContain('/projects/material/src/app/foo/foo.component.less'); + }); + }); + + describe('inlineStyle option', () => { + it('should respect the option value', () => { + const tree = runner.runSchematic( + 'table', {inlineStyle: true, ...baseOptions}, createTestApp()); + + expect(tree.files).not.toContain('/projects/material/src/app/foo/foo.component.css'); + }); + + it('should fallback to the @schematics/angular:component option value', () => { + const tree = runner.runSchematic('table', baseOptions, createTestApp({inlineStyle: true})); + + expect(tree.files).not.toContain('/projects/material/src/app/foo/foo.component.css'); + }); + }); + + describe('inlineTemplate option', () => { + it('should respect the option value', () => { + const tree = runner.runSchematic( + 'table', {inlineTemplate: true, ...baseOptions}, createTestApp()); + + expect(tree.files).not.toContain('/projects/material/src/app/foo/foo.component.html'); + }); + + it('should fallback to the @schematics/angular:component option value', () => { + const tree = runner.runSchematic( + 'table', baseOptions, createTestApp({inlineTemplate: true})); + + expect(tree.files).not.toContain('/projects/material/src/app/foo/foo.component.html'); + }); + }); + + describe('spec option', () => { + it('should respect the option value', () => { + const tree = runner.runSchematic('table', {spec: false, ...baseOptions}, createTestApp()); + + expect(tree.files).not.toContain('/projects/material/src/app/foo/foo.component.spec.ts'); + }); + + it('should fallback to the @schematics/angular:component option value', () => { + const tree = runner.runSchematic('table', baseOptions, createTestApp({skipTests: true})); + + expect(tree.files).not.toContain('/projects/material/src/app/foo/foo.component.spec.ts'); + }); + }); }); diff --git a/src/lib/schematics/table/index.ts b/src/lib/schematics/table/index.ts index ca29ac24a7b..90c7d302852 100644 --- a/src/lib/schematics/table/index.ts +++ b/src/lib/schematics/table/index.ts @@ -18,8 +18,7 @@ import {addModuleImportToModule, findModuleFromOptions} from '../utils/ast'; export default function(options: Schema): Rule { return chain([ buildComponent({...options}, { - template: options.inlineTemplate && - './__path__/__name@dasherize@if-flat__/__name@dasherize__.component.html' + template: './__path__/__name@dasherize@if-flat__/__name@dasherize__.component.html' }), options.skipImport ? noop() : addTableModulesToModule(options) ]); diff --git a/src/lib/schematics/table/schema.json b/src/lib/schematics/table/schema.json index ded294915e1..766e3e99714 100644 --- a/src/lib/schematics/table/schema.json +++ b/src/lib/schematics/table/schema.json @@ -28,13 +28,11 @@ "inlineStyle": { "description": "Specifies if the style will be in the ts file.", "type": "boolean", - "default": false, "alias": "s" }, "inlineTemplate": { "description": "Specifies if the template will be in the ts file.", "type": "boolean", - "default": false, "alias": "t" }, "viewEncapsulation": { @@ -62,8 +60,7 @@ }, "spec": { "type": "boolean", - "description": "Specifies if a spec file is generated.", - "default": true + "description": "Specifies if a spec file is generated." }, "flat": { "type": "boolean", diff --git a/src/lib/schematics/tree/index.ts b/src/lib/schematics/tree/index.ts index b2cc2523ece..726a39c28e5 100644 --- a/src/lib/schematics/tree/index.ts +++ b/src/lib/schematics/tree/index.ts @@ -18,10 +18,8 @@ import {Schema} from './schema'; export default function(options: Schema): Rule { return chain([ buildComponent({...options}, { - template: options.inlineTemplate && - './__path__/__name@dasherize@if-flat__/__name@dasherize__.component.html', - stylesheet: options.inlineStyle && - './__path__/__name@dasherize@if-flat__/__name@dasherize__.component.__styleext__', + template: './__path__/__name@dasherize@if-flat__/__name@dasherize__.component.html', + stylesheet: './__path__/__name@dasherize@if-flat__/__name@dasherize__.component.__styleext__', }), options.skipImport ? noop() : addTreeModulesToModule(options) ]); diff --git a/src/lib/schematics/tree/schema.json b/src/lib/schematics/tree/schema.json index a9e697b514c..9e1182e2ef2 100644 --- a/src/lib/schematics/tree/schema.json +++ b/src/lib/schematics/tree/schema.json @@ -28,13 +28,11 @@ "inlineStyle": { "description": "Specifies if the style will be in the ts file.", "type": "boolean", - "default": false, "alias": "s" }, "inlineTemplate": { "description": "Specifies if the template will be in the ts file.", "type": "boolean", - "default": false, "alias": "t" }, "viewEncapsulation": { @@ -62,8 +60,7 @@ }, "spec": { "type": "boolean", - "description": "Specifies if a spec file is generated.", - "default": true + "description": "Specifies if a spec file is generated." }, "flat": { "type": "boolean", diff --git a/src/lib/schematics/utils/build-component.ts b/src/lib/schematics/utils/build-component.ts index 5ada72e87e1..ad2ec2efe30 100644 --- a/src/lib/schematics/utils/build-component.ts +++ b/src/lib/schematics/utils/build-component.ts @@ -36,10 +36,10 @@ import {buildRelativePath, findModuleFromOptions} from '@schematics/angular/util import {parseName} from '@schematics/angular/utility/parse-name'; import {buildDefaultPath} from '@schematics/angular/utility/project'; import {validateHtmlSelector, validateName} from '@schematics/angular/utility/validation'; -import {resolve, dirname, join} from 'path'; import {readFileSync} from 'fs'; +import {dirname, join, resolve} from 'path'; import * as ts from 'typescript'; -import {determineDefaultStyleExt} from './default-style-ext'; +import {getDefaultComponentOptions} from './schematic-options'; function readIntoSourceFile(host: Tree, modulePath: string): ts.SourceFile { const text = host.read(modulePath); @@ -163,14 +163,17 @@ export function buildComponent(options: ComponentOptions, return (host: Tree, context: FileSystemSchematicContext) => { const workspace = getWorkspace(host); const project = workspace.projects[options.project || workspace.defaultProject]; + const defaultComponentOptions = getDefaultComponentOptions(project); const schematicFilesUrl = './files'; const schematicFilesPath = resolve(dirname(context.schematic.description.path), schematicFilesUrl); - if (!options.styleext) { - options.styleext = determineDefaultStyleExt(project); - } + // Add the default component option values to the options if an option is not explicitly + // specified but a default component option is available. + Object.keys(options) + .filter(optionName => options[optionName] == null && defaultComponentOptions[optionName]) + .forEach(optionName => options[optionName] = defaultComponentOptions[optionName]); if (options.path === undefined) { options.path = buildDefaultPath(project); diff --git a/src/lib/schematics/utils/default-style-ext.ts b/src/lib/schematics/utils/default-style-ext.ts deleted file mode 100644 index 39ce0cd5251..00000000000 --- a/src/lib/schematics/utils/default-style-ext.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {WorkspaceProject} from '@schematics/angular/utility/config'; - -/** - * Style extension that will be used if no default style extension for the CLI project - * could be determined. - */ -const fallbackStyleExtension = 'css'; - -/** - * Determines the default style extension in the Angular CLI project by looking for the default - * component schematic options. This is necessary for now because when creating CLI projects, - * the CLI only makes the default `--style` option available for the `angular:component` schematic. - */ -export function determineDefaultStyleExt(project: WorkspaceProject): string | null { - if (project.schematics && - project.schematics['@schematics/angular:component'] && - project.schematics['@schematics/angular:component']['styleext']) { - - return project.schematics['@schematics/angular:component']['styleext']; - } - - return fallbackStyleExtension; -} diff --git a/src/lib/schematics/utils/schematic-options.ts b/src/lib/schematics/utils/schematic-options.ts new file mode 100644 index 00000000000..cb5ae44fedd --- /dev/null +++ b/src/lib/schematics/utils/schematic-options.ts @@ -0,0 +1,45 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {WorkspaceProject} from '@schematics/angular/utility/config'; + +/** + * Returns the default options for the `@schematics/angular:component` schematic which would + * have been specified at project initialization (ng new or ng init). + * + * This is necessary because the Angular CLI only exposes the default values for the "--style", + * "--inlineStyle", "--skipTests" and "--inlineTemplate" options to the "component" schematic. + */ +export function getDefaultComponentOptions(project: WorkspaceProject) { + // Note: Not all options which are available when running "ng new" will be stored in the + // workspace config. List of options which will be available in the configuration: + // angular/angular-cli/blob/master/packages/schematics/angular/application/index.ts#L109-L131 + return { + styleext: getDefaultComponentOption(project, 'styleext', 'css'), + inlineStyle: getDefaultComponentOption(project, 'inlineStyle', false), + inlineTemplate: getDefaultComponentOption(project, 'inlineTemplate', false), + spec: getDefaultComponentOption(project, 'spec', true), + }; +} + +/** + * Gets the default value for the specified option. The default options will be determined + * by looking at the stored schematic options for `@schematics/angular:component` in the + * CLI workspace configuration. + */ +function getDefaultComponentOption(project: WorkspaceProject, optionName: string, + fallbackValue: T): T | null { + if (project.schematics && + project.schematics['@schematics/angular:component'] && + project.schematics['@schematics/angular:component'][optionName] != null) { + + return project.schematics['@schematics/angular:component'][optionName]; + } + + return fallbackValue; +}