fix(schematics): support app gen with inline-template

This adds the support to generate an application with the `inline-template` flag activated.
Two new utils added: `getDecoratorPropertyValueNode` & `replaceNodeValue`.
Add some tests ensure to test the two ways of generating template, using `templateUrls` and `inlineTemplate`.
Tests are unising the flag `inlineTemplate`.

close #519
This commit is contained in:
ben 2018-08-14 14:31:48 -04:00 committed by Victor Savkin
parent ba5777735f
commit b1b0207496
3 changed files with 107 additions and 8 deletions

View File

@ -240,4 +240,31 @@ describe('app', () => {
).toContain('imports: [RouterTestingModule]');
});
});
describe('template generation mode', () => {
it('should create Nx specific `app.component.html` template', () => {
const tree = schematicRunner.runSchematic(
'app',
{ name: 'myApp', directory: 'myDir' },
appTree
);
expect(
getFileContent(tree, 'apps/my-dir/my-app/src/app/app.component.html')
).toBeTruthy();
expect(
getFileContent(tree, 'apps/my-dir/my-app/src/app/app.component.html')
).toContain('This is an Angular CLI app built with Nrwl Nx!');
});
it("should update `template`'s property of AppComponent with Nx content", () => {
const tree = schematicRunner.runSchematic(
'app',
{ name: 'myApp', directory: 'myDir', inlineTemplate: true },
appTree
);
expect(
getFileContent(tree, 'apps/my-dir/my-app/src/app/app.component.ts')
).toContain('This is an Angular CLI app built with Nrwl Nx!');
});
});
});

View File

@ -13,7 +13,9 @@ import { insertImport } from '@schematics/angular/utility/ast-utils';
import {
addImportToModule,
addImportToTestBed,
getDecoratorPropertyValueNode,
insert,
replaceNodeValue,
updateJsonInTree
} from '../../utils/ast-utils';
import { toFileName } from '../../utils/name-utils';
@ -117,9 +119,27 @@ Nx is designed to help you create and build enterprise grade Angular application
const content = options.routing
? `${baseContent}\n<router-outlet></router-outlet>`
: baseContent;
host.overwrite(
`${options.appProjectRoot}/src/app/app.component.html`,
content
if (!options.inlineTemplate) {
return host.overwrite(
`${options.appProjectRoot}/src/app/app.component.html`,
content
);
}
const modulePath = `${options.appProjectRoot}/src/app/app.component.ts`;
const templateNodeValue = getDecoratorPropertyValueNode(
host,
modulePath,
'Component',
'template',
'@angular/core'
);
replaceNodeValue(
host,
modulePath,
templateNodeValue,
`\`\n${baseContent}\n\`,\n`
);
};
}

View File

@ -238,7 +238,12 @@ export function removeFromNgModule(
}
// Get all the children property assignment of object literals.
const matchingProperty = getMatchingProperty(source, property);
const matchingProperty = getMatchingProperty(
source,
property,
'NgModule',
'@angular/core'
);
if (matchingProperty) {
return [
new RemoveChange(
@ -343,7 +348,12 @@ export function getBootstrapComponent(
source: ts.SourceFile,
moduleClassName: string
): string {
const bootstrap = getMatchingProperty(source, 'bootstrap');
const bootstrap = getMatchingProperty(
source,
'bootstrap',
'NgModule',
'@angular/core'
);
if (!bootstrap) {
throw new Error(`Cannot find bootstrap components in '${moduleClassName}'`);
}
@ -383,9 +393,11 @@ function getMatchingObjectLiteralElement(
function getMatchingProperty(
source: ts.SourceFile,
property: string
property: string,
identifier: string,
module: string
): ts.ObjectLiteralElement {
const nodes = getDecoratorMetadata(source, 'NgModule', '@angular/core');
const nodes = getDecoratorMetadata(source, identifier, module);
let node: any = nodes[0]; // tslint:disable-line:no-any
if (!node) return null;
@ -424,7 +436,12 @@ export function addIncludeToTsConfig(
}
function getListOfRoutes(source: ts.SourceFile): ts.NodeArray<ts.Expression> {
const imports: any = getMatchingProperty(source, 'imports');
const imports: any = getMatchingProperty(
source,
'imports',
'NgModule',
'@angular/core'
);
if (imports.initializer.kind === ts.SyntaxKind.ArrayLiteralExpression) {
const a = imports.initializer as ts.ArrayLiteralExpression;
@ -888,3 +905,38 @@ export function insertImport(
ts.SyntaxKind.StringLiteral
);
}
export function getDecoratorPropertyValueNode(
host: Tree,
modulePath: string,
identifier: string,
property: string,
module: string
) {
const moduleSourceText = host.read(modulePath)!.toString('utf-8');
const moduleSource = ts.createSourceFile(
modulePath,
moduleSourceText,
ts.ScriptTarget.Latest,
true
);
const templateNode = getMatchingProperty(
moduleSource,
property,
identifier,
module
);
return templateNode.getChildAt(templateNode.getChildCount() - 1);
}
export function replaceNodeValue(
host: Tree,
modulePath: string,
node: ts.Node,
content: string
) {
insert(host, modulePath, [
new ReplaceChange(modulePath, node.pos, node.getFullText(), content)
]);
}