UNPKG

39.1 kBPlain TextView Raw
1import * as fs from 'fs-extra';
2import * as path from 'path';
3
4import { ts } from 'ts-morph';
5
6import { Application } from './app/application';
7import Configuration from './app/configuration';
8import FileEngine from './app/engines/file.engine';
9import I18nEngine from './app/engines/i18n.engine';
10
11import { ConfigurationFileInterface } from './app/interfaces/configuration-file.interface';
12import AngularVersionUtil from './utils/angular-version.util';
13import { COMPODOC_DEFAULTS } from './utils/defaults';
14import { logger } from './utils/logger';
15import { ParserUtil } from './utils/parser.util.class';
16import { readConfig, ignoreDirectory } from './utils/utils';
17
18import { cosmiconfigSync } from 'cosmiconfig';
19
20const os = require('os');
21const osName = require('os-name');
22const pkg = require('../package.json');
23const program = require('commander');
24
25const cosmiconfigModuleName = 'compodoc';
26
27let scannedFiles = [];
28let excludeFiles;
29let includeFiles;
30let cwd = process.cwd();
31
32process.setMaxListeners(0);
33
34export class CliApplication extends Application {
35 /**
36 * Run compodoc from the command line.
37 */
38 protected start(): any {
39 function list(val) {
40 return val.split(',');
41 }
42
43 program
44 .version(pkg.version)
45 .usage('<src> [options]')
46 .option(
47 '-c, --config [config]',
48 'A configuration file : .compodocrc, .compodocrc.json, .compodocrc.yaml or compodoc property in package.json'
49 )
50 .option('-p, --tsconfig [config]', 'A tsconfig.json file')
51 .option(
52 '-d, --output [folder]',
53 'Where to store the generated documentation',
54 COMPODOC_DEFAULTS.folder
55 )
56 .option('-y, --extTheme [file]', 'External styling theme file')
57 .option('-n, --name [name]', 'Title documentation', COMPODOC_DEFAULTS.title)
58 .option(
59 '-a, --assetsFolder [folder]',
60 'External assets folder to copy in generated documentation folder'
61 )
62 .option('-o, --open [value]', 'Open the generated documentation')
63 .option(
64 '-t, --silent',
65 "In silent mode, log messages aren't logged in the console",
66 false
67 )
68 .option(
69 '-s, --serve',
70 'Serve generated documentation (default http://localhost:8080/)',
71 false
72 )
73 .option('--host [host]', 'Change default host address')
74 .option('-r, --port [port]', 'Change default serving port', COMPODOC_DEFAULTS.port)
75 .option(
76 '-w, --watch',
77 'Watch source files after serve and force documentation rebuild',
78 false
79 )
80 .option(
81 '-e, --exportFormat [format]',
82 'Export in specified format (json, html)',
83 COMPODOC_DEFAULTS.exportFormat
84 )
85 .option('--files [files]', 'Files provided by external tool, used for coverage test')
86 .option(
87 '--language [language]',
88 'Language used for the generated documentation (de-DE, en-US, es-ES, fr-FR, hu-HU, it-IT, ja-JP, ko-KR, nl-NL, pl-PL, pt-BR, sk-SK, zh-CN)',
89 COMPODOC_DEFAULTS.language
90 )
91 .option(
92 '--theme [theme]',
93 "Choose one of available themes, default is 'gitbook' (laravel, original, material, postmark, readthedocs, stripe, vagrant)"
94 )
95 .option(
96 '--hideGenerator',
97 'Do not print the Compodoc link at the bottom of the page',
98 false
99 )
100 .option(
101 '--toggleMenuItems <items>',
102 "Close by default items in the menu values : ['all'] or one of these ['modules','components','directives','controllers','classes','injectables','guards','interfaces','interceptors','pipes','miscellaneous','additionalPages']",
103 list,
104 COMPODOC_DEFAULTS.toggleMenuItems
105 )
106 .option(
107 '--navTabConfig <tab configs>',
108 `List navigation tab objects in the desired order with two string properties ("id" and "label"). \
109Double-quotes must be escaped with '\\'. \
110Available tab IDs are "info", "readme", "source", "templateData", "styleData", "tree", and "example". \
111Note: Certain tabs will only be shown if applicable to a given dependency`,
112 list,
113 JSON.stringify(COMPODOC_DEFAULTS.navTabConfig)
114 )
115 .option(
116 '--templates [folder]',
117 'Path to directory of Handlebars templates to override built-in templates'
118 )
119 .option('--includes [path]', 'Path of external markdown files to include')
120 .option(
121 '--includesName [name]',
122 'Name of item menu of externals markdown files',
123 COMPODOC_DEFAULTS.additionalEntryName
124 )
125 .option(
126 '--coverageTest [threshold]',
127 'Test command of documentation coverage with a threshold (default 70)'
128 )
129 .option(
130 '--coverageMinimumPerFile [minimum]',
131 'Test command of documentation coverage per file with a minimum (default 0)'
132 )
133 .option(
134 '--coverageTestThresholdFail [true|false]',
135 'Test command of documentation coverage (global or per file) will fail with error or just warn user (true: error, false: warn)',
136 COMPODOC_DEFAULTS.coverageTestThresholdFail
137 )
138 .option('--coverageTestShowOnlyFailed', 'Display only failed files for a coverage test')
139 .option(
140 '--unitTestCoverage [json-summary]',
141 'To include unit test coverage, specify istanbul JSON coverage summary file'
142 )
143 .option(
144 '--disableSourceCode',
145 'Do not add source code tab and links to source code',
146 false
147 )
148 .option('--disableDomTree', 'Do not add dom tree tab', false)
149 .option('--disableTemplateTab', 'Do not add template tab', false)
150 .option('--disableStyleTab', 'Do not add style tab', false)
151 .option('--disableGraph', 'Do not add the dependency graph', false)
152 .option('--disableCoverage', 'Do not add the documentation coverage report', false)
153 .option('--disablePrivate', 'Do not show private in generated documentation', false)
154 .option('--disableProtected', 'Do not show protected in generated documentation', false)
155 .option('--disableInternal', 'Do not show @internal in generated documentation', false)
156 .option(
157 '--disableLifeCycleHooks',
158 'Do not show Angular lifecycle hooks in generated documentation',
159 false
160 )
161 .option(
162 '--disableRoutesGraph',
163 'Do not add the routes graph',
164 COMPODOC_DEFAULTS.disableRoutesGraph
165 )
166 .option('--disableSearch', 'Do not add the search input', false)
167 .option(
168 '--disableDependencies',
169 'Do not add the dependencies list',
170 COMPODOC_DEFAULTS.disableDependencies
171 )
172 .option(
173 '--minimal',
174 'Minimal mode with only documentation. No search, no graph, no coverage.',
175 false
176 )
177 .option('--customFavicon [path]', 'Use a custom favicon')
178 .option('--customLogo [path]', 'Use a custom logo')
179 .option('--gaID [id]', 'Google Analytics tracking ID')
180 .option('--gaSite [site]', 'Google Analytics site name', COMPODOC_DEFAULTS.gaSite)
181 .option(
182 '--maxSearchResults [maxSearchResults]',
183 'Max search results on the results page. To show all results, set to 0',
184 COMPODOC_DEFAULTS.maxSearchResults
185 )
186 .parse(process.argv);
187
188 let outputHelp = () => {
189 program.outputHelp();
190 process.exit(1);
191 };
192
193 const configExplorer = cosmiconfigSync(cosmiconfigModuleName);
194
195 let configExplorerResult;
196
197 let configFile: ConfigurationFileInterface = {};
198
199 const programOptions = program.opts();
200
201 if (programOptions.config) {
202 let configFilePath = programOptions.config;
203 let testConfigFilePath = configFilePath.match(process.cwd());
204 if (testConfigFilePath && testConfigFilePath.length > 0) {
205 configFilePath = configFilePath.replace(process.cwd() + path.sep, '');
206 }
207 configExplorerResult = configExplorer.load(path.resolve(configFilePath));
208 } else {
209 configExplorerResult = configExplorer.search();
210 }
211
212 if (configExplorerResult) {
213 if (typeof configExplorerResult.config !== 'undefined') {
214 configFile = configExplorerResult.config;
215 }
216 }
217
218 if (configFile.output) {
219 Configuration.mainData.output = configFile.output;
220 }
221 if (programOptions.output && programOptions.output !== COMPODOC_DEFAULTS.folder) {
222 Configuration.mainData.output = programOptions.output;
223 }
224
225 if (configFile.extTheme) {
226 Configuration.mainData.extTheme = configFile.extTheme;
227 }
228 if (programOptions.extTheme) {
229 Configuration.mainData.extTheme = programOptions.extTheme;
230 }
231
232 if (configFile.language) {
233 Configuration.mainData.language = configFile.language;
234 }
235 if (programOptions.language) {
236 Configuration.mainData.language = programOptions.language;
237 }
238
239 if (configFile.theme) {
240 Configuration.mainData.theme = configFile.theme;
241 }
242 if (programOptions.theme) {
243 Configuration.mainData.theme = programOptions.theme;
244 }
245
246 if (configFile.name) {
247 Configuration.mainData.documentationMainName = configFile.name;
248 }
249 if (programOptions.name && programOptions.name !== COMPODOC_DEFAULTS.title) {
250 Configuration.mainData.documentationMainName = programOptions.name;
251 }
252
253 if (configFile.assetsFolder) {
254 Configuration.mainData.assetsFolder = configFile.assetsFolder;
255 }
256 if (programOptions.assetsFolder) {
257 Configuration.mainData.assetsFolder = programOptions.assetsFolder;
258 }
259
260 if (configFile.open) {
261 Configuration.mainData.open = configFile.open;
262 }
263 if (programOptions.open) {
264 Configuration.mainData.open = programOptions.open;
265 }
266
267 if (configFile.toggleMenuItems) {
268 Configuration.mainData.toggleMenuItems = configFile.toggleMenuItems;
269 }
270 if (
271 programOptions.toggleMenuItems &&
272 programOptions.toggleMenuItems !== COMPODOC_DEFAULTS.toggleMenuItems
273 ) {
274 Configuration.mainData.toggleMenuItems = programOptions.toggleMenuItems;
275 }
276
277 if (configFile.templates) {
278 Configuration.mainData.templates = configFile.templates;
279 }
280 if (programOptions.templates) {
281 Configuration.mainData.templates = programOptions.templates;
282 }
283
284 if (configFile.navTabConfig) {
285 Configuration.mainData.navTabConfig = configFile.navTabConfig;
286 }
287 if (
288 programOptions.navTabConfig &&
289 JSON.parse(programOptions.navTabConfig).length !== COMPODOC_DEFAULTS.navTabConfig.length
290 ) {
291 Configuration.mainData.navTabConfig = JSON.parse(programOptions.navTabConfig);
292 }
293
294 if (configFile.includes) {
295 Configuration.mainData.includes = configFile.includes;
296 }
297 if (programOptions.includes) {
298 Configuration.mainData.includes = programOptions.includes;
299 }
300
301 if (configFile.includesName) {
302 Configuration.mainData.includesName = configFile.includesName;
303 }
304 if (
305 programOptions.includesName &&
306 programOptions.includesName !== COMPODOC_DEFAULTS.additionalEntryName
307 ) {
308 Configuration.mainData.includesName = programOptions.includesName;
309 }
310
311 if (configFile.silent) {
312 logger.silent = false;
313 }
314 if (programOptions.silent) {
315 logger.silent = false;
316 }
317
318 if (configFile.serve) {
319 Configuration.mainData.serve = configFile.serve;
320 }
321 if (programOptions.serve) {
322 Configuration.mainData.serve = programOptions.serve;
323 }
324
325 if (configFile.host) {
326 Configuration.mainData.host = configFile.host;
327 Configuration.mainData.hostname = configFile.host;
328 }
329 if (programOptions.host) {
330 Configuration.mainData.host = programOptions.host;
331 Configuration.mainData.hostname = programOptions.host;
332 }
333
334 if (configFile.port) {
335 Configuration.mainData.port = configFile.port;
336 }
337 if (programOptions.port && programOptions.port !== COMPODOC_DEFAULTS.port) {
338 Configuration.mainData.port = programOptions.port;
339 }
340
341 if (configFile.watch) {
342 Configuration.mainData.watch = configFile.watch;
343 }
344 if (programOptions.watch) {
345 Configuration.mainData.watch = programOptions.watch;
346 }
347
348 if (configFile.exportFormat) {
349 Configuration.mainData.exportFormat = configFile.exportFormat;
350 }
351 if (
352 programOptions.exportFormat &&
353 programOptions.exportFormat !== COMPODOC_DEFAULTS.exportFormat
354 ) {
355 Configuration.mainData.exportFormat = programOptions.exportFormat;
356 }
357
358 if (configFile.hideGenerator) {
359 Configuration.mainData.hideGenerator = configFile.hideGenerator;
360 }
361 if (programOptions.hideGenerator) {
362 Configuration.mainData.hideGenerator = programOptions.hideGenerator;
363 }
364
365 if (configFile.coverageTest) {
366 Configuration.mainData.coverageTest = true;
367 Configuration.mainData.coverageTestThreshold =
368 typeof configFile.coverageTest === 'string'
369 ? parseInt(configFile.coverageTest, 10)
370 : COMPODOC_DEFAULTS.defaultCoverageThreshold;
371 }
372 if (programOptions.coverageTest) {
373 Configuration.mainData.coverageTest = true;
374 Configuration.mainData.coverageTestThreshold =
375 typeof programOptions.coverageTest === 'string'
376 ? parseInt(programOptions.coverageTest, 10)
377 : COMPODOC_DEFAULTS.defaultCoverageThreshold;
378 }
379
380 if (configFile.coverageMinimumPerFile) {
381 Configuration.mainData.coverageTestPerFile = true;
382 Configuration.mainData.coverageMinimumPerFile =
383 typeof configFile.coverageMinimumPerFile === 'string'
384 ? parseInt(configFile.coverageMinimumPerFile, 10)
385 : COMPODOC_DEFAULTS.defaultCoverageMinimumPerFile;
386 }
387 if (programOptions.coverageMinimumPerFile) {
388 Configuration.mainData.coverageTestPerFile = true;
389 Configuration.mainData.coverageMinimumPerFile =
390 typeof programOptions.coverageMinimumPerFile === 'string'
391 ? parseInt(programOptions.coverageMinimumPerFile, 10)
392 : COMPODOC_DEFAULTS.defaultCoverageMinimumPerFile;
393 }
394
395 if (configFile.coverageTestThresholdFail) {
396 Configuration.mainData.coverageTestThresholdFail =
397 configFile.coverageTestThresholdFail === 'false' ? false : true;
398 }
399 if (programOptions.coverageTestThresholdFail) {
400 Configuration.mainData.coverageTestThresholdFail =
401 programOptions.coverageTestThresholdFail === 'false' ? false : true;
402 }
403
404 if (configFile.coverageTestShowOnlyFailed) {
405 Configuration.mainData.coverageTestShowOnlyFailed =
406 configFile.coverageTestShowOnlyFailed;
407 }
408 if (programOptions.coverageTestShowOnlyFailed) {
409 Configuration.mainData.coverageTestShowOnlyFailed =
410 programOptions.coverageTestShowOnlyFailed;
411 }
412
413 if (configFile.unitTestCoverage) {
414 Configuration.mainData.unitTestCoverage = configFile.unitTestCoverage;
415 }
416 if (programOptions.unitTestCoverage) {
417 Configuration.mainData.unitTestCoverage = programOptions.unitTestCoverage;
418 }
419
420 if (configFile.disableSourceCode) {
421 Configuration.mainData.disableSourceCode = configFile.disableSourceCode;
422 }
423 if (programOptions.disableSourceCode) {
424 Configuration.mainData.disableSourceCode = programOptions.disableSourceCode;
425 }
426
427 if (configFile.disableDomTree) {
428 Configuration.mainData.disableDomTree = configFile.disableDomTree;
429 }
430 if (programOptions.disableDomTree) {
431 Configuration.mainData.disableDomTree = programOptions.disableDomTree;
432 }
433
434 if (configFile.disableTemplateTab) {
435 Configuration.mainData.disableTemplateTab = configFile.disableTemplateTab;
436 }
437 if (programOptions.disableTemplateTab) {
438 Configuration.mainData.disableTemplateTab = programOptions.disableTemplateTab;
439 }
440
441 if (configFile.disableStyleTab) {
442 Configuration.mainData.disableStyleTab = configFile.disableStyleTab;
443 }
444 if (programOptions.disableStyleTab) {
445 Configuration.mainData.disableStyleTab = programOptions.disableStyleTab;
446 }
447
448 if (configFile.disableGraph) {
449 Configuration.mainData.disableGraph = configFile.disableGraph;
450 }
451 if (programOptions.disableGraph) {
452 Configuration.mainData.disableGraph = programOptions.disableGraph;
453 }
454
455 if (configFile.disableCoverage) {
456 Configuration.mainData.disableCoverage = configFile.disableCoverage;
457 }
458 if (programOptions.disableCoverage) {
459 Configuration.mainData.disableCoverage = programOptions.disableCoverage;
460 }
461
462 if (configFile.disablePrivate) {
463 Configuration.mainData.disablePrivate = configFile.disablePrivate;
464 }
465 if (programOptions.disablePrivate) {
466 Configuration.mainData.disablePrivate = programOptions.disablePrivate;
467 }
468
469 if (configFile.disableProtected) {
470 Configuration.mainData.disableProtected = configFile.disableProtected;
471 }
472 if (programOptions.disableProtected) {
473 Configuration.mainData.disableProtected = programOptions.disableProtected;
474 }
475
476 if (configFile.disableInternal) {
477 Configuration.mainData.disableInternal = configFile.disableInternal;
478 }
479 if (programOptions.disableInternal) {
480 Configuration.mainData.disableInternal = programOptions.disableInternal;
481 }
482
483 if (configFile.disableLifeCycleHooks) {
484 Configuration.mainData.disableLifeCycleHooks = configFile.disableLifeCycleHooks;
485 }
486 if (programOptions.disableLifeCycleHooks) {
487 Configuration.mainData.disableLifeCycleHooks = programOptions.disableLifeCycleHooks;
488 }
489
490 if (configFile.disableRoutesGraph) {
491 Configuration.mainData.disableRoutesGraph = configFile.disableRoutesGraph;
492 }
493 if (programOptions.disableRoutesGraph) {
494 Configuration.mainData.disableRoutesGraph = programOptions.disableRoutesGraph;
495 }
496
497 if (configFile.disableSearch) {
498 Configuration.mainData.disableSearch = configFile.disableSearch;
499 }
500 if (programOptions.disableSearch) {
501 Configuration.mainData.disableSearch = programOptions.disableSearch;
502 }
503
504 if (configFile.disableDependencies) {
505 Configuration.mainData.disableDependencies = configFile.disableDependencies;
506 }
507 if (programOptions.disableDependencies) {
508 Configuration.mainData.disableDependencies = programOptions.disableDependencies;
509 }
510
511 if (configFile.minimal) {
512 Configuration.mainData.disableSearch = true;
513 Configuration.mainData.disableRoutesGraph = true;
514 Configuration.mainData.disableGraph = true;
515 Configuration.mainData.disableCoverage = true;
516 }
517 if (programOptions.minimal) {
518 Configuration.mainData.disableSearch = true;
519 Configuration.mainData.disableRoutesGraph = true;
520 Configuration.mainData.disableGraph = true;
521 Configuration.mainData.disableCoverage = true;
522 }
523
524 if (configFile.customFavicon) {
525 Configuration.mainData.customFavicon = configFile.customFavicon;
526 }
527 if (programOptions.customFavicon) {
528 Configuration.mainData.customFavicon = programOptions.customFavicon;
529 }
530
531 if (configFile.customLogo) {
532 Configuration.mainData.customLogo = configFile.customLogo;
533 }
534 if (programOptions.customLogo) {
535 Configuration.mainData.customLogo = programOptions.customLogo;
536 }
537
538 if (configFile.gaID) {
539 Configuration.mainData.gaID = configFile.gaID;
540 }
541 if (programOptions.gaID) {
542 Configuration.mainData.gaID = programOptions.gaID;
543 }
544
545 if (configFile.gaSite) {
546 Configuration.mainData.gaSite = configFile.gaSite;
547 }
548 if (programOptions.gaSite && programOptions.gaSite !== COMPODOC_DEFAULTS.gaSite) {
549 Configuration.mainData.gaSite = programOptions.gaSite;
550 }
551
552 if (!this.isWatching) {
553 if (!logger.silent) {
554 console.log(`Compodoc v${pkg.version}`);
555 } else {
556 console.log(fs.readFileSync(path.join(__dirname, '../src/banner')).toString());
557 console.log(pkg.version);
558 console.log('');
559 console.log(`TypeScript version used by Compodoc : ${ts.version}`);
560 console.log('');
561
562 if (FileEngine.existsSync(cwd + path.sep + 'package.json')) {
563 const packageData = FileEngine.getSync(cwd + path.sep + 'package.json');
564 if (packageData) {
565 const parsedData = JSON.parse(packageData);
566 const projectDevDependencies = parsedData.devDependencies;
567 if (projectDevDependencies && projectDevDependencies.typescript) {
568 const tsProjectVersion = AngularVersionUtil.cleanVersion(
569 projectDevDependencies.typescript
570 );
571 console.log(
572 `TypeScript version of current project : ${tsProjectVersion}`
573 );
574 console.log('');
575 }
576 }
577 }
578 console.log(`Node.js version : ${process.version}`);
579 console.log('');
580 console.log(`Operating system : ${osName(os.platform(), os.release())}`);
581 console.log('');
582 }
583 }
584
585 if (configExplorerResult) {
586 if (typeof configExplorerResult.config !== 'undefined') {
587 logger.info(`Using configuration file : ${configExplorerResult.filepath}`);
588 }
589 }
590
591 if (!configExplorerResult) {
592 logger.warn(`No configuration file found, switching to CLI flags.`);
593 }
594
595 if (programOptions.language && !I18nEngine.supportLanguage(programOptions.language)) {
596 logger.warn(
597 `The language ${programOptions.language} is not available, falling back to ${I18nEngine.fallbackLanguage}`
598 );
599 }
600
601 if (programOptions.tsconfig && typeof programOptions.tsconfig === 'boolean') {
602 logger.error(`Please provide a tsconfig file.`);
603 process.exit(1);
604 }
605
606 if (configFile.tsconfig) {
607 Configuration.mainData.tsconfig = configFile.tsconfig;
608 }
609 if (programOptions.tsconfig) {
610 Configuration.mainData.tsconfig = programOptions.tsconfig;
611 }
612
613 if (programOptions.maxSearchResults) {
614 Configuration.mainData.maxSearchResults = programOptions.maxSearchResults;
615 }
616
617 if (configFile.files) {
618 scannedFiles = configFile.files;
619 }
620 if (configFile.exclude) {
621 excludeFiles = configFile.exclude;
622 }
623 if (configFile.include) {
624 includeFiles = configFile.include;
625 }
626
627 /**
628 * Check --files argument call
629 */
630 const argv = require('minimist')(process.argv.slice(2));
631 if (argv && argv.files) {
632 Configuration.mainData.hasFilesToCoverage = true;
633 if (typeof argv.files === 'string') {
634 super.setFiles([argv.files]);
635 } else {
636 super.setFiles(argv.files);
637 }
638 }
639
640 if (programOptions.serve && !Configuration.mainData.tsconfig && programOptions.output) {
641 // if -s & -d, serve it
642 if (!FileEngine.existsSync(Configuration.mainData.output)) {
643 logger.error(`${Configuration.mainData.output} folder doesn't exist`);
644 process.exit(1);
645 } else {
646 logger.info(
647 `Serving documentation from ${Configuration.mainData.output} at http://${Configuration.mainData.hostname}:${programOptions.port}`
648 );
649 super.runWebServer(Configuration.mainData.output);
650 }
651 } else if (
652 programOptions.serve &&
653 !Configuration.mainData.tsconfig &&
654 !programOptions.output
655 ) {
656 // if only -s find ./documentation, if ok serve, else error provide -d
657 if (!FileEngine.existsSync(Configuration.mainData.output)) {
658 logger.error('Provide output generated folder with -d flag');
659 process.exit(1);
660 } else {
661 logger.info(
662 `Serving documentation from ${Configuration.mainData.output} at http://${Configuration.mainData.hostname}:${programOptions.port}`
663 );
664 super.runWebServer(Configuration.mainData.output);
665 }
666 } else if (Configuration.mainData.hasFilesToCoverage) {
667 if (programOptions.coverageMinimumPerFile) {
668 logger.info('Run documentation coverage test for files');
669 super.testCoverage();
670 } else {
671 logger.error('Missing coverage configuration');
672 }
673 } else {
674 if (programOptions.hideGenerator) {
675 Configuration.mainData.hideGenerator = true;
676 }
677
678 if (Configuration.mainData.tsconfig && program.args.length === 0) {
679 /**
680 * tsconfig file provided only
681 */
682 let testTsConfigPath = Configuration.mainData.tsconfig.indexOf(process.cwd());
683 if (testTsConfigPath !== -1) {
684 Configuration.mainData.tsconfig = Configuration.mainData.tsconfig.replace(
685 process.cwd() + path.sep,
686 ''
687 );
688 }
689
690 if (!FileEngine.existsSync(Configuration.mainData.tsconfig)) {
691 logger.error(
692 `"${Configuration.mainData.tsconfig}" file was not found in the current directory`
693 );
694 process.exit(1);
695 } else {
696 let _file = path.join(
697 path.join(process.cwd(), path.dirname(Configuration.mainData.tsconfig)),
698 path.basename(Configuration.mainData.tsconfig)
699 );
700 // use the current directory of tsconfig.json as a working directory
701 cwd = _file.split(path.sep).slice(0, -1).join(path.sep);
702 logger.info('Using tsconfig file ', _file);
703
704 let tsConfigFile = readConfig(_file);
705 if (tsConfigFile.files) {
706 scannedFiles = tsConfigFile.files;
707 // Normalize path of these files
708 scannedFiles = scannedFiles.map(scannedFile => {
709 return cwd + path.sep + scannedFile;
710 });
711 }
712
713 // even if files are supplied with "files" attributes, enhance the array with includes
714 excludeFiles = tsConfigFile.exclude || [];
715 includeFiles = tsConfigFile.include || [];
716
717 if (scannedFiles.length > 0) {
718 includeFiles = [...includeFiles, ...scannedFiles];
719 }
720
721 let excludeParser = new ParserUtil(),
722 includeParser = new ParserUtil();
723
724 excludeParser.init(excludeFiles, cwd);
725 includeParser.init(includeFiles, cwd);
726
727 let startCwd = cwd;
728
729 let excludeParserTestFilesWithCwdDepth = excludeParser.testFilesWithCwdDepth();
730 if (!excludeParserTestFilesWithCwdDepth.status) {
731 startCwd = excludeParser.updateCwd(
732 cwd,
733 excludeParserTestFilesWithCwdDepth.level
734 );
735 }
736 let includeParserTestFilesWithCwdDepth = includeParser.testFilesWithCwdDepth();
737 if (!includeParser.testFilesWithCwdDepth().status) {
738 startCwd = includeParser.updateCwd(
739 cwd,
740 includeParserTestFilesWithCwdDepth.level
741 );
742 }
743
744 let finder = require('findit2')(startCwd || '.');
745
746 finder.on('directory', function (dir, stat, stop) {
747 if (ignoreDirectory(dir)) {
748 stop();
749 }
750 });
751
752 finder.on('file', (file, stat) => {
753 if (/(spec|\.d)\.ts/.test(file)) {
754 logger.warn('Ignoring', file);
755 } else if (
756 excludeParser.testFile(file) &&
757 (path.extname(file) === '.ts' || path.extname(file) === '.tsx')
758 ) {
759 logger.warn('Excluding', file);
760 } else if (includeFiles.length > 0) {
761 /**
762 * If include provided in tsconfig, use only this source,
763 * and not files found with global findit scan in working directory
764 */
765 if (
766 (path.extname(file) === '.ts' || path.extname(file) === '.tsx') &&
767 includeParser.testFile(file)
768 ) {
769 logger.debug('Including', file);
770 scannedFiles.push(file);
771 } else {
772 if (path.extname(file) === '.ts' || path.extname(file) === '.tsx') {
773 logger.warn('Excluding', file);
774 }
775 }
776 } else {
777 logger.debug('Including', file);
778 scannedFiles.push(file);
779 }
780 });
781
782 finder.on('end', () => {
783 super.setFiles(scannedFiles);
784 if (programOptions.coverageTest || programOptions.coverageTestPerFile) {
785 logger.info('Run documentation coverage test');
786 super.testCoverage();
787 } else {
788 super.generate();
789 }
790 });
791 }
792 } else if (Configuration.mainData.tsconfig && program.args.length > 0) {
793 /**
794 * tsconfig file provided with source folder in arg
795 */
796 let testTsConfigPath = Configuration.mainData.tsconfig.indexOf(process.cwd());
797 if (testTsConfigPath !== -1) {
798 Configuration.mainData.tsconfig = Configuration.mainData.tsconfig.replace(
799 process.cwd() + path.sep,
800 ''
801 );
802 }
803
804 let sourceFolder = program.args[0];
805 if (!FileEngine.existsSync(sourceFolder)) {
806 logger.error(
807 `Provided source folder ${sourceFolder} was not found in the current directory`
808 );
809 process.exit(1);
810 } else {
811 logger.info('Using provided source folder');
812
813 if (!FileEngine.existsSync(Configuration.mainData.tsconfig)) {
814 logger.error(
815 `"${Configuration.mainData.tsconfig}" file was not found in the current directory`
816 );
817 process.exit(1);
818 } else {
819 let _file = path.join(
820 path.join(process.cwd(), path.dirname(Configuration.mainData.tsconfig)),
821 path.basename(Configuration.mainData.tsconfig)
822 );
823 // use the current directory of tsconfig.json as a working directory
824 cwd = _file.split(path.sep).slice(0, -1).join(path.sep);
825 logger.info('Using tsconfig file ', _file);
826
827 let tsConfigFile = readConfig(_file);
828 if (tsConfigFile.files) {
829 scannedFiles = tsConfigFile.files;
830 // Normalize path of these files
831 scannedFiles = scannedFiles.map(scannedFile => {
832 return cwd + path.sep + scannedFile;
833 });
834 }
835
836 // even if files are supplied with "files" attributes, enhance the array with includes
837 excludeFiles = tsConfigFile.exclude || [];
838 includeFiles = tsConfigFile.include || [];
839
840 if (scannedFiles.length > 0) {
841 includeFiles = [...includeFiles, ...scannedFiles];
842 }
843
844 let excludeParser = new ParserUtil(),
845 includeParser = new ParserUtil();
846
847 excludeParser.init(excludeFiles, cwd);
848 includeParser.init(includeFiles, cwd);
849
850 let startCwd = sourceFolder;
851
852 let excludeParserTestFilesWithCwdDepth =
853 excludeParser.testFilesWithCwdDepth();
854 if (!excludeParserTestFilesWithCwdDepth.status) {
855 startCwd = excludeParser.updateCwd(
856 cwd,
857 excludeParserTestFilesWithCwdDepth.level
858 );
859 }
860 let includeParserTestFilesWithCwdDepth =
861 includeParser.testFilesWithCwdDepth();
862 if (!includeParser.testFilesWithCwdDepth().status) {
863 startCwd = includeParser.updateCwd(
864 cwd,
865 includeParserTestFilesWithCwdDepth.level
866 );
867 }
868
869 let finder = require('findit2')(path.resolve(startCwd));
870
871 finder.on('directory', function (dir, stat, stop) {
872 if (ignoreDirectory(dir)) {
873 stop();
874 }
875 });
876
877 finder.on('file', (file, stat) => {
878 if (/(spec|\.d)\.ts/.test(file)) {
879 logger.warn('Ignoring', file);
880 } else if (excludeParser.testFile(file)) {
881 logger.warn('Excluding', file);
882 } else if (includeFiles.length > 0) {
883 /**
884 * If include provided in tsconfig, use only this source,
885 * and not files found with global findit scan in working directory
886 */
887 if (path.extname(file) === '.ts' && includeParser.testFile(file)) {
888 logger.debug('Including', file);
889 scannedFiles.push(file);
890 } else {
891 if (path.extname(file) === '.ts') {
892 logger.warn('Excluding', file);
893 }
894 }
895 } else {
896 logger.debug('Including', file);
897 scannedFiles.push(file);
898 }
899 });
900
901 finder.on('end', () => {
902 super.setFiles(scannedFiles);
903 if (programOptions.coverageTest || programOptions.coverageTestPerFile) {
904 logger.info('Run documentation coverage test');
905 super.testCoverage();
906 } else {
907 super.generate();
908 }
909 });
910 }
911 }
912 } else {
913 logger.error('tsconfig.json file was not found, please use -p flag');
914 outputHelp();
915 }
916 }
917 }
918}