diff --git a/packages/angular-cli/blueprints/component/index.js b/packages/angular-cli/blueprints/component/index.js index b5c529fe9774..326c8c624e54 100644 --- a/packages/angular-cli/blueprints/component/index.js +++ b/packages/angular-cli/blueprints/component/index.js @@ -7,6 +7,7 @@ const getFiles = Blueprint.prototype.files; const stringUtils = require('ember-cli-string-utils'); const astUtils = require('../../utilities/ast-utils'); const NodeHost = require('@angular-cli/ast-tools').NodeHost; +const getConstConfig = require('../../utilities/get-const-config').default; module.exports = { description: '', @@ -15,7 +16,7 @@ module.exports = { { name: 'flat', type: Boolean, default: false }, { name: 'inline-template', type: Boolean, aliases: ['it'] }, { name: 'inline-style', type: Boolean, aliases: ['is'] }, - { name: 'prefix', type: Boolean, default: true }, + { name: 'prefix', type: String, default: null }, { name: 'spec', type: Boolean }, { name: 'view-encapsulation', type: String, aliases: ['ve'] }, { name: 'change-detection', type: String, aliases: ['cd'] }, @@ -37,13 +38,19 @@ module.exports = { this.dynamicPath = parsedPath; + var modulePrefix = getConstConfig(this.project, this.dynamicPath.dir, 'ModulePrefix'); + var defaultPrefix = ''; if (this.project.ngConfig && this.project.ngConfig.apps[0] && this.project.ngConfig.apps[0].prefix) { - defaultPrefix = this.project.ngConfig.apps[0].prefix + '-'; + defaultPrefix = this.project.ngConfig.apps[0].prefix; } - var prefix = this.options.prefix ? defaultPrefix : ''; + + var prefix = (this.options.prefix === 'false' || this.options.prefix === '') + ? '' : (this.options.prefix || modulePrefix || defaultPrefix); + prefix = prefix && `${prefix}-`; + this.selector = stringUtils.dasherize(prefix + parsedPath.name); if (this.selector.indexOf('-') === -1) { diff --git a/packages/angular-cli/blueprints/directive/index.js b/packages/angular-cli/blueprints/directive/index.js index 216e115a79f6..f01ccb88f2a5 100644 --- a/packages/angular-cli/blueprints/directive/index.js +++ b/packages/angular-cli/blueprints/directive/index.js @@ -6,13 +6,15 @@ const findParentModule = require('../../utilities/find-parent-module').default; const NodeHost = require('@angular-cli/ast-tools').NodeHost; const Blueprint = require('../../ember-cli/lib/models/blueprint'); const getFiles = Blueprint.prototype.files; +const getConstConfig = require('../../utilities/get-const-config').default; + module.exports = { description: '', availableOptions: [ { name: 'flat', type: Boolean, default: true }, - { name: 'prefix', type: Boolean, default: true }, + { name: 'prefix', type: String, default: null }, { name: 'spec', type: Boolean }, { name: 'skip-import', type: Boolean, default: false } ], @@ -32,13 +34,19 @@ module.exports = { this.dynamicPath = parsedPath; + var modulePrefix = getConstConfig(this.project, this.dynamicPath.dir, 'ModulePrefix'); + var defaultPrefix = ''; if (this.project.ngConfig && this.project.ngConfig.apps[0] && this.project.ngConfig.apps[0].prefix) { defaultPrefix = this.project.ngConfig.apps[0].prefix; } - var prefix = this.options.prefix ? `${defaultPrefix}-` : ''; + + var prefix = (this.options.prefix === 'false' || this.options.prefix === '') + ? '' : (this.options.prefix || modulePrefix || defaultPrefix); + prefix = prefix && `${prefix}-`; + this.selector = stringUtils.camelize(prefix + parsedPath.name); return parsedPath.name; diff --git a/packages/angular-cli/blueprints/module/files/__path__/__name__.module.ts b/packages/angular-cli/blueprints/module/files/__path__/__name__.module.ts index 2505c216531f..ce04effc1689 100644 --- a/packages/angular-cli/blueprints/module/files/__path__/__name__.module.ts +++ b/packages/angular-cli/blueprints/module/files/__path__/__name__.module.ts @@ -2,6 +2,9 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common';<% if (routing) { %> import { <%= classifiedModuleName %>RoutingModule } from './<%= dasherizedModuleName %>-routing.module';<% } %> +<% if (prefix) { %> +export const ModulePrefix = '<%= prefix %>'; +<% } %> @NgModule({ imports: [ CommonModule<% if (routing) { %>, diff --git a/packages/angular-cli/blueprints/module/index.js b/packages/angular-cli/blueprints/module/index.js index c82dfdfa282a..95609eebfc10 100644 --- a/packages/angular-cli/blueprints/module/index.js +++ b/packages/angular-cli/blueprints/module/index.js @@ -8,7 +8,8 @@ module.exports = { availableOptions: [ { name: 'spec', type: Boolean }, - { name: 'routing', type: Boolean, default: false } + { name: 'routing', type: Boolean, default: false }, + { name: 'prefix', type: String, default: null} ], normalizeEntityName: function (entityName) { @@ -27,7 +28,8 @@ module.exports = { return { dynamicPath: this.dynamicPath.dir, spec: options.spec, - routing: options.routing + routing: options.routing, + prefix: options.prefix }; }, @@ -68,7 +70,7 @@ module.exports = { options.route = false; options.inlineTemplate = false; options.inlineStyle = false; - options.prefix = true; + options.prefix = null; options.spec = true; return Blueprint.load(path.join(__dirname, '../component')).install(options); } diff --git a/packages/angular-cli/utilities/get-const-config.ts b/packages/angular-cli/utilities/get-const-config.ts new file mode 100644 index 000000000000..7e79730ba6fa --- /dev/null +++ b/packages/angular-cli/utilities/get-const-config.ts @@ -0,0 +1,22 @@ +import findParentModule from './find-parent-module'; +import * as astUtils from './ast-utils'; +import * as ts from 'typescript'; + +export default function getConstConfig(project: any, dir: string, identifier: string): string { + let modulePrefix = ''; + try { + let pathToModule = findParentModule(project, dir); + astUtils.getSourceNodes(astUtils.getSource(pathToModule)) + .last((node: ts.Node) => { + // tslint:disable-next-line:no-bitwise + return (node.flags & ts.NodeFlags.Export) !== 0 + && node.getText().includes(identifier); + }) + .subscribe((node: ts.Node) => { + modulePrefix = /= ?['"]([\w-]+)["']/.exec(node.getText())[1]; + }); + } catch (e) { + console.log(`no const configuration found for ${identifier} in the parent module\n\t`); + } + return modulePrefix; +} diff --git a/tests/acceptance/generate-component.spec.js b/tests/acceptance/generate-component.spec.js index 20bd25460bbe..07f04348bc38 100644 --- a/tests/acceptance/generate-component.spec.js +++ b/tests/acceptance/generate-component.spec.js @@ -150,6 +150,26 @@ describe('Acceptance: ng generate component', function () { }); }); + it('mycomp --prefix= will not prefix selector', () => { + return ng(['generate', 'component', 'mycomp', '--prefix=']) + .then(() => { + var testPath = path.join(root, 'tmp', 'foo', 'src', 'app', 'mycomp', 'mycomp.component.ts'); + expect(existsSync(testPath)).to.equal(true); + var contents = fs.readFileSync(testPath, 'utf8'); + expect(contents.indexOf('selector: \'mycomp\'') === -1).to.equal(false); + }); + }); + + it('mycomp --prefix=test will prefix selector with \'test-\'', () => { + return ng(['generate', 'component', 'mycomp', '--prefix=test']) + .then(() => { + var testPath = path.join(root, 'tmp', 'foo', 'src', 'app', 'mycomp', 'mycomp.component.ts'); + expect(existsSync(testPath)).to.equal(true); + var contents = fs.readFileSync(testPath, 'utf8'); + expect(contents.indexOf('selector: \'test-mycomp\'') === -1).to.equal(false); + }); + }); + it('myComp will succeed', () => { return ng(['generate', 'component', 'myComp']) .then(() => { diff --git a/tests/acceptance/generate-module.spec.js b/tests/acceptance/generate-module.spec.js index a4e38274da4c..28eab5e399d2 100644 --- a/tests/acceptance/generate-module.spec.js +++ b/tests/acceptance/generate-module.spec.js @@ -2,6 +2,8 @@ const ng = require('../helpers/ng'); const tmp = require('../helpers/tmp'); +var fs = require('fs-extra'); + const existsSync = require('exists-sync'); const expect = require('chai').expect; @@ -36,6 +38,7 @@ describe('Acceptance: ng generate module', function () { expect(existsSync(path.join(testPath, 'my-module', 'my-module.module.ts'))).to.equal(true); expect(existsSync(path.join(testPath, 'my-module', 'my-module.module.spec.ts'))).to.equal(false); expect(existsSync(path.join(testPath, 'my-module', 'my-module.component.ts'))).to.equal(false); + }); }); @@ -55,6 +58,15 @@ describe('Acceptance: ng generate module', function () { }); }); + it('ng generate module my-module --prefix=my', function () { + return ng(['generate', 'module', 'my-module', '--prefix=my']).then(() => { + expect(existsSync(path.join(testPath, 'my-module', 'my-module.module.ts'))).to.equal(true); + var contents = fs.readFileSync(path.join(testPath, 'my-module', 'my-module.module.ts'), 'utf8'); + expect(contents.indexOf('export const ModulePrefix = \'my\';') === -1).to.equal(false); + expect(existsSync(path.join(testPath, 'my-module', 'my-module.module.spec.ts'))).to.equal(false); + expect(existsSync(path.join(testPath, 'my-module', 'my-module.component.ts'))).to.equal(false); }); + }); + it('ng generate module TwoWord', function () { return ng(['generate', 'module', 'TwoWord']).then(() => { expect(existsSync(path.join(testPath, 'two-word', 'two-word.module.ts'))).to.equal(true);