diff --git a/docs/documentation/new.md b/docs/documentation/new.md index 9400ce2ef5e2..2d1c37799591 100644 --- a/docs/documentation/new.md +++ b/docs/documentation/new.md @@ -34,7 +34,20 @@ Default applications are created in a directory of the same name, with an initia --inline-style (alias: -is) default value: false

- Should have an inline style. + Determine whether the generated AppComponent styles will be inlined in the component code, or a seperate styles file. +

+ + +
+ inline-style-all +

+ --inline-style-all (alias: -isa) default value: false +

+

+ Determine whether all generated components' styles will be inlined in the component code, or a seperate styles file. +

+

+ You can later change the value in .angular-cli.json (defaults.component.inlineStyle).

@@ -44,7 +57,20 @@ Default applications are created in a directory of the same name, with an initia --inline-template (alias: -it) default value: false

- Should have an inline template. + Determine whether the generated AppComponent template will be inlined in the component code, or a seperate template file. +

+ + +
+ inline-template-all +

+ --inline-template-all (alias: -ita) default value: false +

+

+ Determine whether all generated components' templates will be inlined in the component code, or a seperate template file. +

+

+ You can later change the value in .angular-cli.json (defaults.component.inlineTemplate).

diff --git a/packages/@angular/cli/blueprints/ng/files/__path__/app/app.component.ts b/packages/@angular/cli/blueprints/ng/files/__path__/app/app.component.ts index b047b38a8947..e27843c1c26b 100644 --- a/packages/@angular/cli/blueprints/ng/files/__path__/app/app.component.ts +++ b/packages/@angular/cli/blueprints/ng/files/__path__/app/app.component.ts @@ -4,7 +4,7 @@ import { Component } from '@angular/core'; selector: '<%= prefix %>-root',<% if (inlineTemplate) { %> template: `

- {{title}} + Welcome to {{title}}!!

<% if (routing) { %> <% } %> `,<% } else { %> diff --git a/packages/@angular/cli/blueprints/ng/files/angular-cli.json b/packages/@angular/cli/blueprints/ng/files/angular-cli.json index 46815b975627..0d1e3f3bf49f 100644 --- a/packages/@angular/cli/blueprints/ng/files/angular-cli.json +++ b/packages/@angular/cli/blueprints/ng/files/angular-cli.json @@ -52,7 +52,10 @@ }, "defaults": { "styleExt": "<%= styleExt %>",<% if (!minimal) { %> - "component": {}<% } else { %> + "component": { + "inlineStyle": <%= inlineStyleAll %>, + "inlineTemplate": <%= inlineTemplateAll %> + }<% } else { %> "component": { "spec": false, "inlineStyle": true, diff --git a/packages/@angular/cli/blueprints/ng/index.ts b/packages/@angular/cli/blueprints/ng/index.ts index 01ca7c0120da..ac47223fe1ab 100644 --- a/packages/@angular/cli/blueprints/ng/index.ts +++ b/packages/@angular/cli/blueprints/ng/index.ts @@ -1,7 +1,7 @@ -import {CliConfig} from '../../models/config'; +import { CliConfig } from '../../models/config'; -const Blueprint = require('../../ember-cli/lib/models/blueprint'); -const path = require('path'); +const Blueprint = require('../../ember-cli/lib/models/blueprint'); +const path = require('path'); const stringUtils = require('ember-cli-string-utils'); const getFiles = Blueprint.prototype.files; @@ -15,25 +15,23 @@ export default Blueprint.extend({ { name: 'routing', type: Boolean, default: false }, { name: 'inline-style', type: Boolean, default: false, aliases: ['is'] }, { name: 'inline-template', type: Boolean, default: false, aliases: ['it'] }, + { name: 'inline-style-all', type: Boolean, default: false, aliases: ['isa'] }, + { name: 'inline-template-all', type: Boolean, default: false, aliases: ['ita'] }, { name: 'skip-git', type: Boolean, default: false, aliases: ['sg'] }, - { name: 'minimal', - type: Boolean, - default: false, - description: 'Should create a minimal app.' - } + { name: 'minimal', type: Boolean, default: false } ], - beforeInstall: function(options: any) { + beforeInstall: function (options: any) { if (options.ignoredUpdateFiles && options.ignoredUpdateFiles.length > 0) { return Blueprint.ignoredUpdateFiles = Blueprint.ignoredUpdateFiles.concat(options.ignoredUpdateFiles); } }, - locals: function(options: any) { + locals: function (options: any) { if (options.minimal) { - options.inlineStyle = true; - options.inlineTemplate = true; + options.inlineStyleAll = true; + options.inlineTemplateAll = true; options.skipTests = true; } @@ -63,39 +61,38 @@ export default Blueprint.extend({ styleExt: this.styleExt, relativeRootPath: relativeRootPath, routing: options.routing, - inlineStyle: options.inlineStyle, - inlineTemplate: options.inlineTemplate, + inlineStyle: options.inlineStyle || options.inlineStyleAll, + inlineTemplate: options.inlineTemplate || options.inlineTemplateAll, + inlineStyleAll: options.inlineStyleAll, + inlineTemplateAll: options.inlineTemplateAll, tests: this.tests, minimal: options.minimal }; }, - files: function() { + files: function () { let fileList = getFiles.call(this) as Array; - if (this.options && !this.options.routing) { - fileList = fileList.filter(p => p.indexOf('app-routing.module.ts') < 0); - } - if (this.options && this.options.inlineTemplate) { - fileList = fileList.filter(p => p.indexOf('app.component.html') < 0); - } - if (this.options && this.options.inlineStyle) { - fileList = fileList.filter(p => p.indexOf('app.component.__styleext__') < 0); - } - if (this.options && this.options.skipGit) { - fileList = fileList.filter(p => p.indexOf('gitignore') < 0); - } - - if (this.options && this.options.skipTests) { - fileList = fileList.filter(p => p.indexOf('app.component.spec.ts') < 0); - } - - if (this.options && this.options.minimal) { - const toRemoveList: RegExp[] = [/e2e\//, /editorconfig/, /README/, /karma.conf.js/, - /protractor.conf.js/, /test.ts/, /tsconfig.spec.json/, /tslint.json/, /favicon.ico/]; - fileList = fileList.filter(p => { - return !toRemoveList.some(re => re.test(p)); + if (this.options) { + const inlineTemplate = this.options.inlineTemplate || this.options.inlineTemplateAll; + const inlineStyle = this.options.inlineStyle || this.options.inlineStyleAll; + const fileFilters: { filter: boolean, fileName: string }[] = [ + { filter: !this.options.routing, fileName: 'app-routing.module.ts' }, + { filter: inlineTemplate , fileName: 'app.component.html' }, + { filter: inlineStyle, fileName: 'app.component.__styleext__' }, + { filter: this.options.skipGit, fileName: 'gitignore' }, + { filter: this.options.skipTests, fileName: 'app.component.spec.ts' } + ]; + + fileFilters.filter(f => f.filter).forEach(({fileName}) => { + fileList = fileList.filter(p => p.indexOf(fileName) < 0); }); + + if (this.options.minimal) { + const toRemoveList: RegExp[] = [/e2e\//, /editorconfig/, /README/, /karma.conf.js/, + /protractor.conf.js/, /test.ts/, /tsconfig.spec.json/, /tslint.json/, /favicon.ico/]; + fileList = fileList.filter(p => !toRemoveList.some(re => re.test(p))); + } } const cliConfig = CliConfig.fromProject(); diff --git a/packages/@angular/cli/commands/init.ts b/packages/@angular/cli/commands/init.ts index b4c309d73655..a85fcf2adb92 100644 --- a/packages/@angular/cli/commands/init.ts +++ b/packages/@angular/cli/commands/init.ts @@ -21,6 +21,8 @@ const InitCommand: any = Command.extend({ { name: 'routing', type: Boolean, default: false }, { name: 'inline-style', type: Boolean, default: false, aliases: ['is'] }, { name: 'inline-template', type: Boolean, default: false, aliases: ['it'] }, + { name: 'inline-style-all', type: Boolean, default: false, aliases: ['isa'] }, + { name: 'inline-template-all', type: Boolean, default: false, aliases: ['ita'] }, { name: 'minimal', type: Boolean, diff --git a/packages/@angular/cli/commands/new.ts b/packages/@angular/cli/commands/new.ts index b4f61766613b..88b028532635 100644 --- a/packages/@angular/cli/commands/new.ts +++ b/packages/@angular/cli/commands/new.ts @@ -119,21 +119,49 @@ const NewCommand = Command.extend({ type: Boolean, default: false, aliases: ['is'], - description: 'Should have an inline style.' + description: oneLine` + Determine whether the generated AppComponent styles will be + inlined in the component code, or a seperate styles file. + ` + }, + { + name: 'inline-style-all', + type: Boolean, + default: false, + aliases: ['isa'], + description: oneLine` + Determine whether all generated components' styles will be + inlined in the component code, or a seperate styles file. + ${changeLater('defaults.component.inlineStyle')}. + ` }, { name: 'inline-template', type: Boolean, default: false, aliases: ['it'], - description: 'Should have an inline template.' - }, - { + description: oneLine` + Determine whether the generated AppComponent template will be + inlined in the component code, or a seperate template file. + ` + }, + { + name: 'inline-template-all', + type: Boolean, + default: false, + aliases: ['ita'], + description: oneLine` + Determine whether all generated components' templates will be + inlined in the component code, or a seperate template file. + ${changeLater('defaults.component.inlineTemplate')}. + ` + }, + { name: 'minimal', type: Boolean, default: false, description: 'Should create a minimal app.' - } + } ], isProject: function (projectPath: string) { diff --git a/packages/@angular/cli/tasks/init.ts b/packages/@angular/cli/tasks/init.ts index ca5c746541e9..514824aa9d8c 100644 --- a/packages/@angular/cli/tasks/init.ts +++ b/packages/@angular/cli/tasks/init.ts @@ -76,6 +76,8 @@ export default Task.extend({ routing: commandOptions.routing, inlineStyle: commandOptions.inlineStyle, inlineTemplate: commandOptions.inlineTemplate, + inlineStyleAll: commandOptions.inlineStyleAll, + inlineTemplateAll: commandOptions.inlineTemplateAll, minimal: commandOptions.minimal, ignoredUpdateFiles: ['favicon.ico'], skipGit: commandOptions.skipGit, diff --git a/tests/acceptance/new.spec.ts b/tests/acceptance/new.spec.ts index bee6d38ef874..31340b1f209b 100644 --- a/tests/acceptance/new.spec.ts +++ b/tests/acceptance/new.spec.ts @@ -8,28 +8,29 @@ import { forEach } from 'lodash'; const ng = require('../helpers/ng'); const tmp = require('../helpers/tmp'); +const readConfigFile = require('../helpers/config-file'); const walkSync = require('walk-sync'); const SilentError = require('silent-error'); const Blueprint = require('@angular/cli/ember-cli/lib/models/blueprint'); const root = process.cwd(); +const commonNewParams = ['new', 'foo', '--skip-install', '--skip-git']; - -describe('Acceptance: ng new', function () { - beforeEach(function () { - return tmp.setup('./tmp').then(function () { +describe('Acceptance: ng new', () => { + beforeEach(() => { + return tmp.setup('./tmp').then(() => { process.chdir('./tmp'); }); }); - afterEach(function () { + afterEach(function() { this.timeout(10000); return tmp.teardown('./tmp'); }); function confirmBlueprintedForDir(dir: string) { - return function () { + return () => { let blueprintPath = path.join(root, dir, 'files'); let expected: string[] = walkSync(blueprintPath); let actual = walkSync('.').sort(); @@ -59,23 +60,23 @@ describe('Acceptance: ng new', function () { it('requires a valid name (!)', () => { return ng(['new', '!', '--skip-install', '--skip-git', '--inline-template']) - .then(() => { throw new Error(); }, () => {}); + .then(() => { throw new Error(); }, () => { }); }); it('requires a valid name (abc-.)', () => { return ng(['new', 'abc-.', '--skip-install', '--skip-git', '--inline-template']) - .then(() => { throw new Error(); }, () => {}); + .then(() => { throw new Error(); }, () => { }); }); it('requires a valid name (abc-)', () => { return ng(['new', 'abc-', '--skip-install', '--skip-git', '--inline-template']) - .then(() => { throw new Error(); }, () => {}); + .then(() => { throw new Error(); }, () => { }); }); it('requires a valid name (abc-def-)', () => { return ng(['new', 'abc-def-', '--skip-install', '--skip-git', '--inline-template']) - .then(() => { throw new Error(); }, () => {}); + .then(() => { throw new Error(); }, () => { }); }); it('requires a valid name (abc-123)', () => { return ng(['new', 'abc-123', '--skip-install', '--skip-git', '--inline-template']) - .then(() => { throw new Error(); }, () => {}); + .then(() => { throw new Error(); }, () => { }); }); it('requires a valid name (abc)', () => { return ng(['new', 'abc', '--skip-install', '--skip-git', '--inline-template']); @@ -84,20 +85,20 @@ describe('Acceptance: ng new', function () { return ng(['new', 'abc-def', '--skip-install', '--skip-git', '--inline-template']); }); - it('ng new foo, where foo does not yet exist, works', function () { + it('ng new foo, where foo does not yet exist, works', () => { return ng(['new', 'foo', '--skip-install']).then(confirmBlueprinted); }); - it('ng new with empty app does throw exception', function () { + it('ng new with empty app does throw exception', () => { expect(ng(['new', ''])).to.throw; }); - it('ng new without app name does throw exception', function () { + it('ng new without app name does throw exception', () => { expect(ng(['new', ''])).to.throw; }); - it('ng new with app name creates new directory and has a dasherized package name', function () { - return ng(['new', 'FooApp', '--skip-install', '--skip-git']).then(function () { + it('ng new with app name creates new directory and has a dasherized package name', () => { + return ng(['new', 'FooApp', '--skip-install', '--skip-git']).then(() => { expect(!fs.pathExistsSync('FooApp')); const pkgJson = JSON.parse(fs.readFileSync('package.json', 'utf8')); @@ -105,8 +106,8 @@ describe('Acceptance: ng new', function () { }); }); - it('ng new has a .editorconfig file', function () { - return ng(['new', 'FooApp', '--skip-install', '--skip-git']).then(function () { + it('ng new has a .editorconfig file', () => { + return ng(['new', 'FooApp', '--skip-install', '--skip-git']).then(() => { expect(!fs.pathExistsSync('FooApp')); const editorConfig = fs.readFileSync('.editorconfig', 'utf8'); @@ -114,10 +115,10 @@ describe('Acceptance: ng new', function () { }); }); - it('Cannot run ng new, inside of Angular CLI project', function () { - return ng(['new', 'foo', '--skip-install', '--skip-git']) - .then(function () { - return ng(['new', 'foo', '--skip-install', '--skip-git']).then(() => { + it('Cannot run ng new, inside of Angular CLI project', () => { + return ng([...commonNewParams]) + .then(() => { + return ng([...commonNewParams]).then(() => { throw new SilentError('Cannot run ng new, inside of Angular CLI project should fail.'); }, () => { expect(!fs.pathExistsSync('foo')); @@ -126,14 +127,14 @@ describe('Acceptance: ng new', function () { .then(confirmBlueprinted); }); - it('ng new without skip-git flag creates .git dir', function () { - return ng(['new', 'foo', '--skip-install']).then(function () { + it('ng new without skip-git flag creates .git dir', () => { + return ng(['new', 'foo', '--skip-install']).then(() => { expect(fs.pathExistsSync('.git')); }); }); - it('ng new with --dry-run does not create new directory', function () { - return ng(['new', 'foo', '--dry-run']).then(function () { + it('ng new with --dry-run does not create new directory', () => { + return ng(['new', 'foo', '--dry-run']).then(() => { const cwd = process.cwd(); expect(cwd).to.not.match(/foo/, 'does not change cwd to foo in a dry run'); expect(!fs.pathExistsSync(path.join(cwd, 'foo')), 'does not create new directory'); @@ -141,9 +142,9 @@ describe('Acceptance: ng new', function () { }); }); - it('ng new with --directory uses given directory name and has correct package name', function () { - return ng(['new', 'foo', '--skip-install', '--skip-git', '--directory=bar']) - .then(function () { + it('ng new with --directory uses given directory name and has correct package name', () => { + return ng([...commonNewParams, '--directory=bar']) + .then(() => { const cwd = process.cwd(); expect(cwd).to.not.match(/foo/, 'does not use app name for directory name'); expect(!fs.pathExistsSync(path.join(cwd, 'foo')), 'does not create new directory with app name'); @@ -157,7 +158,7 @@ describe('Acceptance: ng new', function () { }); it('ng new --inline-template does not generate a template file', () => { - return ng(['new', 'foo', '--skip-install', '--skip-git', '--inline-template']) + return ng([...commonNewParams, '--inline-template']) .then(() => { const templateFile = path.join('src', 'app', 'app.component.html'); expect(fs.pathExistsSync(templateFile)).to.equal(false); @@ -165,7 +166,7 @@ describe('Acceptance: ng new', function () { }); it('ng new --inline-style does not gener a style file', () => { - return ng(['new', 'foo', '--skip-install', '--skip-git', '--inline-style']) + return ng([...commonNewParams, '--inline-style']) .then(() => { const styleFile = path.join('src', 'app', 'app.component.css'); expect(fs.pathExistsSync(styleFile)).to.equal(false); @@ -173,11 +174,42 @@ describe('Acceptance: ng new', function () { }); it('should skip spec files when passed --skip-tests', () => { - return ng(['new', 'foo', '--skip-install', '--skip-git', '--skip-tests']) + return ng([...commonNewParams, '--skip-tests']) .then(() => { const specFile = path.join('src', 'app', 'app.component.spec.ts'); expect(fs.pathExistsSync(specFile)).to.equal(false); }); }); + it(`should not set inlineStyle in .angular-cli.json when passed --inline-style`, () => { + return ng([...commonNewParams, `--inline-style`]) + .then(() => { + const configFile = readConfigFile(); + expect(configFile.defaults.component.inlineStyle).to.equal(false); + }); + }); + + it(`should not set inlineTemplate in .angular-cli.json when passed --inline-template`, () => { + return ng([...commonNewParams, `--inline-template`]) + .then(() => { + const configFile = readConfigFile(); + expect(configFile.defaults.component.inlineTemplate).to.equal(false); + }); + }); + + it(`should set inlineStyle in .angular-cli.json when passed --inline-style-all`, () => { + return ng([...commonNewParams, `--inline-style-all`]) + .then(() => { + const configFile = readConfigFile(); + expect(configFile.defaults.component.inlineStyle).to.equal(true); + }); + }); + + it(`should set inlineTemplate in .angular-cli.json when passed --inline-template-all`, () => { + return ng([...commonNewParams, `--inline-template-all`]) + .then(() => { + const configFile = readConfigFile(); + expect(configFile.defaults.component.inlineTemplate).to.equal(true); + }); + }); }); diff --git a/tests/e2e/tests/commands/new/inline-with-all.ts b/tests/e2e/tests/commands/new/inline-with-all.ts new file mode 100644 index 000000000000..0c029d444f30 --- /dev/null +++ b/tests/e2e/tests/commands/new/inline-with-all.ts @@ -0,0 +1,25 @@ +// tslint:disable:max-line-length +import { createProject } from '../../../utils/project'; +import { ng } from '../../../utils/process'; +import { expectFileNotToExist, expectFileToExist } from '../../../utils/fs'; +import { join } from 'path'; + +export default () => { + const componentDir = join('src', 'app', 'test-component'); + const componentFile = (file: string) => join(componentDir, file); + + return Promise.resolve() + .then(() => createProject('test-inline-with-all', '--inline-template-all', '--inline-style-all')) + .then(() => expectFileNotToExist('src/app/app.component.html')) + .then(() => expectFileNotToExist('src/app/app.component.css')) + .then(() => ng('generate', 'component', 'test-component')) + + .then(() => expectFileToExist(componentDir)) + .then(() => expectFileToExist(componentFile('test-component.component.ts'))) + .then(() => expectFileToExist(componentFile('test-component.component.spec.ts'))) + .then(() => expectFileNotToExist(componentFile('test-component.component.html'))) + .then(() => expectFileNotToExist(componentFile('test-component.component.css'))) + + // Try to run the unit tests. + .then(() => ng('test', '--single-run')); +}; diff --git a/tests/e2e/tests/commands/new/inline-without-all.ts b/tests/e2e/tests/commands/new/inline-without-all.ts new file mode 100644 index 000000000000..e52534269c36 --- /dev/null +++ b/tests/e2e/tests/commands/new/inline-without-all.ts @@ -0,0 +1,25 @@ +// tslint:disable:max-line-length +import { createProject } from '../../../utils/project'; +import { ng } from '../../../utils/process'; +import { expectFileNotToExist, expectFileToExist } from '../../../utils/fs'; +import { join } from 'path'; + +export default () => { + const componentDir = join('src', 'app', 'test-component'); + const componentFile = (file: string) => join(componentDir, file); + + return Promise.resolve() + .then(() => createProject('test-inline-without-all', '--inline-template', '--inline-style')) + .then(() => expectFileNotToExist('src/app/app.component.html')) + .then(() => expectFileNotToExist('src/app/app.component.css')) + .then(() => ng('generate', 'component', 'test-component')) + + .then(() => expectFileToExist(componentDir)) + .then(() => expectFileToExist(componentFile('test-component.component.ts'))) + .then(() => expectFileToExist(componentFile('test-component.component.spec.ts'))) + .then(() => expectFileToExist(componentFile('test-component.component.html'))) + .then(() => expectFileToExist(componentFile('test-component.component.css'))) + + // Try to run the unit tests. + .then(() => ng('test', '--single-run')); +}; diff --git a/tests/helpers/config-file.js b/tests/helpers/config-file.js new file mode 100644 index 000000000000..94c19be6c23d --- /dev/null +++ b/tests/helpers/config-file.js @@ -0,0 +1,7 @@ +const fs = require('fs-extra'); + +const readConfigFile = () => { + return JSON.parse(fs.readFileSync('.angular-cli.json', 'utf8')); +}; + +module.exports = readConfigFile; \ No newline at end of file