Skip to content
This repository was archived by the owner on Apr 4, 2025. It is now read-only.

Commit 4ad3358

Browse files
Broccohansl
authored andcommitted
feat(@schematics/angular): Add directive schematic
1 parent 18fe75d commit 4ad3358

File tree

5 files changed

+162
-0
lines changed

5 files changed

+162
-0
lines changed

packages/schematics/angular/collection.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@
1515
"description": "Create an Angular component.",
1616
"schema": "./component/schema.json"
1717
},
18+
"directive": {
19+
"factory": "./directive",
20+
"description": "Create an Angular directive.",
21+
"schema": "./directive/schema.json"
22+
},
1823
"enum": {
1924
"factory": "./enum",
2025
"description": "Create an enumeration.",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { <%= classify(name) %>Directive } from './<%= dasherize(name) %>.directive';
2+
3+
describe('<%= classify(name) %>Directive', () => {
4+
it('should create an instance', () => {
5+
const directive = new <%= classify(name) %>Directive();
6+
expect(directive).toBeTruthy();
7+
});
8+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Directive } from '@angular/core';
2+
3+
@Directive({
4+
selector: '[<%= selector %>]'
5+
})
6+
export class <%= classify(name) %>Directive {
7+
8+
constructor() { }
9+
10+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/**
2+
* @license
3+
* Copyright Google Inc. 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+
// TODO: replace `options: any` with an actual type generated from the schema.
9+
// tslint:disable:no-any
10+
import {addDeclarationToModule} from '../utility/ast-utils';
11+
import {InsertChange} from '../utility/change';
12+
13+
import {
14+
Rule,
15+
Tree,
16+
apply,
17+
branchAndMerge,
18+
chain,
19+
filter,
20+
mergeWith,
21+
move,
22+
noop,
23+
template,
24+
url,
25+
} from '@angular-devkit/schematics';
26+
import * as stringUtils from '../strings';
27+
28+
import 'rxjs/add/operator/merge';
29+
import * as ts from 'typescript';
30+
import { buildRelativePath, findModule } from '../utility/find-module';
31+
32+
33+
function addDeclarationToNgModule(options: any): Rule {
34+
return (host: Tree) => {
35+
if (options.skipImport) {
36+
return host;
37+
}
38+
39+
let modulePath;
40+
if (options.module) {
41+
if (!host.exists(options.module)) {
42+
throw new Error(`Module specified (${options.module}) does not exist.`);
43+
}
44+
modulePath = options.module;
45+
} else {
46+
modulePath = findModule(host, options.sourceDir + '/' + options.path);
47+
}
48+
49+
const sourceText = host.read(modulePath) !.toString('utf-8');
50+
const source = ts.createSourceFile(modulePath, sourceText, ts.ScriptTarget.Latest, true);
51+
52+
const componentPath = `/${options.sourceDir}/${options.path}/`
53+
+ (options.flat ? '' : stringUtils.dasherize(options.name) + '/')
54+
+ stringUtils.dasherize(options.name)
55+
+ '.component';
56+
const relativePath = buildRelativePath(modulePath, componentPath);
57+
const changes = addDeclarationToModule(source, modulePath,
58+
stringUtils.classify(`${options.name}Component`),
59+
relativePath);
60+
const recorder = host.beginUpdate(modulePath);
61+
for (const change of changes) {
62+
if (change instanceof InsertChange) {
63+
recorder.insertLeft(change.pos, change.toAdd);
64+
}
65+
}
66+
host.commitUpdate(recorder);
67+
68+
return host;
69+
};
70+
}
71+
72+
73+
function buildSelector(options: any) {
74+
let selector = stringUtils.dasherize(options.name);
75+
if (options.prefix) {
76+
selector = `${options.prefix}-${selector}`;
77+
}
78+
79+
return selector;
80+
}
81+
82+
export default function (options: any): Rule {
83+
options.selector = options.selector || buildSelector(options);
84+
85+
const templateSource = apply(url('./files'), [
86+
options.spec ? noop() : filter(path => !path.endsWith('.spec.ts')),
87+
template({
88+
...stringUtils,
89+
'if-flat': (s: string) => options.flat ? '' : s,
90+
...options,
91+
}),
92+
move(options.sourceDir),
93+
]);
94+
95+
return chain([
96+
branchAndMerge(chain([
97+
addDeclarationToNgModule(options),
98+
mergeWith(templateSource),
99+
])),
100+
]);
101+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"$schema": "http://json-schema.org/schema",
3+
"id": "SchematicsAngularClass",
4+
"title": "Angular Class Options Schema",
5+
"type": "object",
6+
"properties": {
7+
"name": {
8+
"type": "string"
9+
},
10+
"path": {
11+
"type": "string",
12+
"default": "app"
13+
},
14+
"sourceDir": {
15+
"type": "string",
16+
"default": "src"
17+
},
18+
"spec": {
19+
"type": "boolean",
20+
"description": "Specifies if a spec file is generated.",
21+
"default": false
22+
},
23+
"skipImport": {
24+
"type": "boolean",
25+
"default": false
26+
},
27+
"selector": {
28+
"type": "string"
29+
},
30+
"flat": {
31+
"type": "boolean",
32+
"default": false
33+
}
34+
},
35+
"required": [
36+
"name"
37+
]
38+
}

0 commit comments

Comments
 (0)