-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathIgniteUIForAngularTemplate.ts
210 lines (186 loc) · 7.64 KB
/
IgniteUIForAngularTemplate.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
import {
AddTemplateArgs, App, ControlExtraConfiguration, FS_TOKEN, IFileSystem, NPM_ANGULAR,
NPM_DOCK_MANAGER, Template, TemplateDependency, Util, resolvePackage
} from "@igniteui/cli-core";
import { AngularTypeScriptFileUpdate } from "@igniteui/angular-templates";
import * as path from "path";
export class IgniteUIForAngularTemplate implements Template {
public components: string[];
public controlGroup: string;
public listInComponentTemplates: boolean = true;
public addAsNgModelDeclaration: boolean = true;
public listInCustomTemplates: boolean = false;
public id: string;
public name: string;
public description: string;
public framework: string = "angular";
public projectType: string = "igx-ts";
public hasExtraConfiguration: boolean = false;
public packages: string[] = [];
public dependencies: TemplateDependency[] = [];
public delimiters = {
content: {
end: `%>`,
start: `<%=`
},
path: {
end: `__`,
start: `__`
}
};
public get templatePaths(): string[] {
return [path.join(this.rootPath, "files")];
}
constructor(private rootPath: string) {
}
public generateConfig(name: string, options: {}): { [key: string]: any } {
if (options["modulePath"] && !Util.fileExists(path.join(process.cwd(), `src\\app`, options["modulePath"]))) {
Util.error(`Wrong module path provided: ${options["modulePath"]}. No components were added!`);
return Promise.resolve(false);
}
return Object.assign({}, options["extraConfig"], this.getBaseVariables(name));
}
//TODO: rename name to fullName for clarity + in all other places fileName to fullName
public registerInProject(projectPath: string, name: string, options?: AddTemplateArgs) {
let modulePath = "app.module.ts";
if (options && options.modulePath) {
modulePath = options.modulePath;
}
// D.P. Don't use the top-level import as that chains import of typescript
// which slows down execution of the entire component noticeably (template loading)
// https://www.typescriptlang.org/docs/handbook/modules.html#dynamic-module-loading-in-nodejs
// tslint:disable-next-line:variable-name
const TsUpdate: typeof AngularTypeScriptFileUpdate =
// tslint:disable-next-line:no-submodule-imports
require("@igniteui/angular-templates").AngularTypeScriptFileUpdate;
const mainModulePath = path.join(projectPath, `src/app/${modulePath}`);
const folderName = this.folderName(name);
const fileName = this.fileName(name);
const componentFilePath = path.join(projectPath, `src/app/${folderName}/${fileName}.component.ts`);
const className = `${Util.className(Util.nameFromPath(name))}Component`;
// standalone components
if (!this.fileExists(mainModulePath)) {
const appRoutesPath = "src/app/app.routes.ts";
if (!(options && options.skipRoute) && this.fileExists(appRoutesPath)) {
const routesConfigPath = path.join(projectPath, appRoutesPath);
const rountesConfig = new TsUpdate(routesConfigPath, true, { indentSize: 2, singleQuotes: true });
rountesConfig.addRoute({
modulePath: Util.relativePath(routesConfigPath, componentFilePath, true, true),
path: this.fileName(name),
data: { text: Util.nameFromPath(name) },
identifierName: className
});
rountesConfig.finalize();
}
const componentFile = new TsUpdate(componentFilePath, true, { indentSize: 2, singleQuotes: true });
for (const dep of this.dependencies) {
if (dep.from && dep.from.startsWith(".")) {
// relative file dependency
const copy = Object.assign({}, dep);
copy.from = Util.relativePath(
componentFilePath,
path.join(projectPath, copy.from!),
true,
true);
componentFile.addStandaloneComponentMeta(dep,
Util.applyDelimiters(this.getBaseVariables(name), this.delimiters.content));
continue;
}
componentFile.addStandaloneComponentMeta(dep,
Util.applyDelimiters(this.getBaseVariables(name), this.delimiters.content)
);
}
componentFile.finalize();
return;
}
// ngModule based components
if (!(options && options.skipRoute) && this.fileExists("src/app/app-routing.module.ts")) {
//1) import the component class name,
//2) and populate the Routes array with the path and component
//for example: { path: 'combo', component: ComboComponent }
const routingModulePath = path.join(projectPath, "src/app/app-routing.module.ts");
const routingModule = new TsUpdate(routingModulePath, false, { indentSize: 2, singleQuotes: true });
routingModule.addRoute({
modulePath: Util.relativePath(routingModulePath, componentFilePath, true, true),
path: this.fileName(name),
data: { text: Util.nameFromPath(name) },
identifierName: className
});
routingModule.finalize();
}
//3) add an import of the component class from its file location.
//4) populate the declarations portion of the @NgModule with the component class name.
const mainModule = new TsUpdate(mainModulePath, false, { indentSize: 2, singleQuotes: true });
mainModule.addNgModuleMeta({
declare: this.addAsNgModelDeclaration ? [className] : [],
from: Util.relativePath(mainModulePath, componentFilePath, true, true),
export: modulePath !== "app.module.ts" ? [className] : []
},
Util.applyDelimiters(this.getBaseVariables(name), this.delimiters.content),
true // multiline
);
// import IgxModules and other dependencies
for (const dep of this.dependencies) {
if (dep.from && dep.from.startsWith(".")) {
// relative file dependency
const copy = Object.assign({}, dep);
copy.from = Util.relativePath(mainModulePath, path.join(projectPath, copy.from!), true, true);
mainModule.addNgModuleMeta(copy,
Util.applyDelimiters(this.getBaseVariables(name), this.delimiters.content),
true // multiline
);
} else {
mainModule.addNgModuleMeta(dep,
Util.applyDelimiters(this.getBaseVariables(name), this.delimiters.content),
true // multiline
);
}
}
mainModule.finalize();
}
public getExtraConfiguration(): ControlExtraConfiguration[] {
return [];
}
public setExtraConfiguration(extraConfigKeys: {}) { }
public fileExists(filePath: string): boolean {
return App.container.get<IFileSystem>(FS_TOKEN).fileExists(filePath);
}
protected getBaseVariables(name: string): { [key: string]: string } {
const config = {};
config["name"] = Util.nameFromPath(name);
config["ClassName"] = Util.className(Util.nameFromPath(name));
config["path"] = this.folderName(name);
config["filePrefix"] = this.fileName(name);
config["description"] = this.description;
config["cliVersion"] = Util.version();
config["camelCaseName"] = Util.camelCase(name);
config["igxPackage"] = resolvePackage(NPM_ANGULAR);
config["dockManagerPackage"] = resolvePackage(NPM_DOCK_MANAGER);
/** 'nameMerged' is never used igx templates, removed */
return config;
}
protected folderName(pathName: string): string {
//TODO: should remove the spaces
const parts = path.parse(pathName);
let folderName = pathName;
if (parts.dir) {
folderName = path.join(parts.dir, parts.name);
folderName = folderName.replace(/\\/g, "/");
// TODO: config-based "src/app"?
const relative = path.join(process.cwd(), "src/app", folderName);
// path.join will also resolve any '..' segments
// so if relative result doesn't start with CWD it's out of project root
if (!relative.startsWith(process.cwd())) {
Util.error(`Path ${"src/app/" + folderName} is not valid!`, "red");
process.exit(1);
}
//clean up potential leading spaces in folder names (`path/ name`):
folderName = folderName.replace(/\/\s+/g, "/");
}
return Util.lowerDashed(folderName);
}
protected fileName(pathName: string): string {
const name = Util.nameFromPath(pathName);
return Util.lowerDashed(name);
}
}