Skip to content

Commit 5ff451d

Browse files
committed
Improved parsing of the @NgModule decorator.
1 parent abe3073 commit 5ff451d

File tree

1 file changed

+98
-23
lines changed

1 file changed

+98
-23
lines changed

src/commands/modulesToMarkdown.ts

Lines changed: 98 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,6 @@ export interface INgModule {
1313
}
1414

1515
export class NgModule implements INgModule {
16-
constructor(private data: INgModule) {
17-
this.imports = data.imports;
18-
this.exports = data.exports;
19-
this.declarations = data.declarations;
20-
this.entryComponents = data.entryComponents;
21-
this.providers = data.providers;
22-
this.bootstrap = data.bootstrap;
23-
}
2416
public imports: string[] = [];
2517
public exports: string[] = [];
2618
public declarations: string[] = [];
@@ -59,16 +51,16 @@ export class ModulesToMarkdown {
5951
modules.push(module);
6052
}
6153
});
62-
markdownContent = markdownContent +
54+
markdownContent = markdownContent +
6355
'## Modules in workspace\n\n' +
6456
'| Module | Declarations | Imports | Exports | Bootstrap | Providers | Entry points |\n' +
6557
'| ---| --- | --- | --- | --- | --- | --- |\n';
6658
let modulesMarkdown: string = '';
6759
modules.forEach(module => {
68-
markdownContent = markdownContent + '| ' + module.moduleName + ' | ' + module.moduleStats().join(' | ') + ' |\n';
60+
markdownContent = markdownContent + '| ' + module.moduleName + ' | ' + module.moduleStats().join(' | ') + ' |\n';
6961
modulesMarkdown = modulesMarkdown + this.generateModuleMarkdown(module);
7062
});
71-
markdownContent = markdownContent + '\n' +modulesMarkdown;
63+
markdownContent = markdownContent + '\n' + modulesMarkdown;
7264
if (errors.length > 0) {
7365
this.showErrors(errors);
7466
}
@@ -85,9 +77,9 @@ export class ModulesToMarkdown {
8577
var match = regex.exec(fileContents.toString());
8678
if (match !== null) {
8779
const moduleName = match[2];
88-
const moduleContents = this.convertNgModuleToParsableJson(match[1]);
80+
const moduleContents = match[1];
8981
try {
90-
const module: NgModule = new NgModule(JSON.parse(moduleContents));
82+
const module: NgModule = this.parseModuleContents(moduleContents);
9183
module.filename = filename;
9284
module.moduleName = moduleName;
9385
module.moduleContents = moduleContents;
@@ -99,17 +91,100 @@ export class ModulesToMarkdown {
9991
}
10092
}
10193

102-
private convertNgModuleToParsableJson(moduleContents: string): string {
94+
private parseModuleContents(moduleContents: string): NgModule {
10395
moduleContents = moduleContents.replace(/\s*?\/\/.*$/igm, () => ''); // Remove comments
104-
moduleContents = moduleContents.replace(/\{\s*provide:\s*(.+?)\s*,\s*use\w+:\s*(.+?)\s*(,\s.*?)*\s*?\}[\s\}]*/igms, (str, provided, provider) => `"${provided.replace(/['"]/gms, '')} provided by ${provider.replace(/[\{\} ']/igms, '').replace(':', '=')}"`); // format providers ;
105-
moduleContents = moduleContents.replace("'", "\""); // Single quotes to double-quotes
106-
moduleContents = moduleContents.replace(/\s*?(\w+)[,\r\n]\s*?/igms, (str, identifier) => `"${identifier}",`); // quotes around array items
107-
moduleContents = moduleContents.replace(/(\w+\.\w+\(\))[,\r\n]/igms, (str, identifier) => `"${identifier}",`); // quotes around array items
108-
moduleContents = moduleContents.replace(/\[\s*([\w_\(\)\.]+?)\s*\]/igms, (str, identifier) => `"${identifier}"`); // quotes around array items
109-
moduleContents = moduleContents.replace(/(\w+\.\w+\().*?(\))[,\r\n]/igms, (str, identifier, idEnd) => `"${identifier}...${idEnd}",`); // quotes around array items
110-
moduleContents = moduleContents.replace(/("\s*),(\s+\])/igms, (str, quote, arrayEnd) => quote + arrayEnd); // Remove illegal empty array ending
111-
moduleContents = moduleContents.replace(/(\w+)\s*:/g, (str, identifier) => `"${identifier}":`); // quotes around identifiers
112-
return moduleContents;
96+
const module = new NgModule();
97+
let section = this.getSection(moduleContents, 'imports');
98+
if (section.length > 0) {
99+
module.imports = this.parseSection(section);
100+
}
101+
section = this.getSection(moduleContents, 'exports');
102+
if (section.length > 0) {
103+
module.exports = this.parseSection(section);
104+
}
105+
section = this.getSection(moduleContents, 'declarations');
106+
if (section.length > 0) {
107+
module.declarations = this.parseSection(section);
108+
}
109+
section = this.getSection(moduleContents, 'entryComponents');
110+
if (section.length > 0) {
111+
module.entryComponents = this.parseSection(section);
112+
}
113+
section = this.getSection(moduleContents, 'providers');
114+
if (section.length > 0) {
115+
module.providers = this.parseSection(section);
116+
}
117+
section = this.getSection(moduleContents, 'bootstrap');
118+
if (section.length > 0) {
119+
module.bootstrap = this.parseSection(section);
120+
}
121+
return module;
122+
}
123+
124+
private getSection(moduleContents: string, sectionName: string): string {
125+
const regex = new RegExp("\\s*" + sectionName + ":\\s*\\[", "igms");
126+
const match = regex.exec(moduleContents);
127+
let section = '';
128+
if(match) {
129+
let endSectionFound = false;
130+
let inBrackets = 0;
131+
for(let currentPos = match.index; currentPos < moduleContents.length && !endSectionFound; currentPos++){
132+
let currentChar = moduleContents.charAt(currentPos);
133+
switch(currentChar){
134+
case '[':
135+
inBrackets++;
136+
break;
137+
case ']':
138+
inBrackets--;
139+
if(inBrackets === 0) {
140+
endSectionFound = true;
141+
section = moduleContents.substr(match.index + match[0].length, currentPos - match.index - match[0].length);
142+
}
143+
}
144+
}
145+
}
146+
return section;
147+
}
148+
149+
private parseSection(sectionContents: string): string[] {
150+
const result: string[] = [];
151+
let currentElement = '';
152+
let inBrackets = 0;
153+
for (let currentPos = 0; currentPos < sectionContents.length; currentPos++) {
154+
let currentChar = sectionContents.charAt(currentPos);
155+
switch (currentChar) {
156+
case ',':
157+
if (inBrackets === 0) {
158+
currentElement = currentElement.replace(/^\s+|\s+$|[\r\t\n|,]/igms, '');
159+
if (currentElement.length > 0) {
160+
result.push(currentElement);
161+
}
162+
currentElement = '';
163+
} else {
164+
currentElement += currentChar;
165+
}
166+
break;
167+
case '{':
168+
case '(':
169+
case '[':
170+
inBrackets++;
171+
currentElement += currentChar;
172+
break;
173+
case '}':
174+
case ')':
175+
case ']':
176+
inBrackets--;
177+
currentElement += currentChar;
178+
break;
179+
default:
180+
currentElement += currentChar;
181+
}
182+
}
183+
currentElement = currentElement.replace(/^\s+|\s+$|[\r\t\n|,]/igms, '');
184+
if (currentElement.length > 0) {
185+
result.push(currentElement);
186+
}
187+
return result;
113188
}
114189

115190
private generateModuleMarkdown(module: NgModule): string {

0 commit comments

Comments
 (0)