-
Notifications
You must be signed in to change notification settings - Fork 678
/
PackagePlugin.ts
128 lines (112 loc) · 4.3 KB
/
PackagePlugin.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
import * as Path from 'path';
import * as FS from 'fs';
import * as ts from 'typescript';
import { Reflection } from '../../models/reflections/abstract';
import { Component, ConverterComponent } from '../components';
import { Converter } from '../converter';
import { Context } from '../context';
import { BindOption } from '../../utils';
/**
* A handler that tries to find the package.json and readme.md files of the
* current project.
*
* The handler traverses the file tree upwards for each file processed by the processor
* and records the nearest package info files it can find. Within the resolve files, the
* contents of the found files will be read and appended to the ProjectReflection.
*/
@Component({name: 'package'})
export class PackagePlugin extends ConverterComponent {
@BindOption('readme')
readme!: string;
/**
* The file name of the found readme.md file.
*/
private readmeFile?: string;
/**
* The file name of the found package.json file.
*/
private packageFile?: string;
/**
* List of directories the handler already inspected.
*/
private visited!: string[];
/**
* Should the readme file be ignored?
*/
private noReadmeFile?: boolean;
/**
* Create a new PackageHandler instance.
*/
initialize() {
this.listenTo(this.owner, {
[Converter.EVENT_BEGIN]: this.onBegin,
[Converter.EVENT_FILE_BEGIN]: this.onBeginDocument,
[Converter.EVENT_RESOLVE_BEGIN]: this.onBeginResolve
});
}
/**
* Triggered when the converter begins converting a project.
*
* @param context The context object describing the current state the converter is in.
*/
private onBegin(context: Context) {
this.readmeFile = undefined;
this.packageFile = undefined;
this.visited = [];
let readme = this.readme;
this.noReadmeFile = (readme === 'none');
if (!this.noReadmeFile && readme) {
readme = Path.resolve(readme);
if (FS.existsSync(readme)) {
this.readmeFile = readme;
}
}
}
/**
* Triggered when the converter begins converting a source file.
*
* @param context The context object describing the current state the converter is in.
* @param reflection The reflection that is currently processed.
* @param node The node that is currently processed if available.
*/
private onBeginDocument(context: Context, reflection: Reflection, node?: ts.SourceFile) {
const packageAndReadmeFound = () => (this.noReadmeFile || this.readmeFile) && this.packageFile;
const reachedTopDirectory = dirName => dirName === Path.resolve(Path.join(dirName, '..'));
const visitedDirBefore = dirName => this.visited.includes(dirName);
if (!node) {
return;
}
const fileName = node.fileName;
let dirName = Path.resolve(Path.dirname(fileName));
while (!packageAndReadmeFound() && !reachedTopDirectory(dirName) && !visitedDirBefore(dirName)) {
FS.readdirSync(dirName).forEach((file) => {
const lowercaseFileName = file.toLowerCase();
if (!this.noReadmeFile && !this.readmeFile && lowercaseFileName === 'readme.md') {
this.readmeFile = Path.join(dirName, file);
}
if (!this.packageFile && lowercaseFileName === 'package.json') {
this.packageFile = Path.join(dirName, file);
}
});
this.visited.push(dirName);
dirName = Path.resolve(Path.join(dirName, '..'));
}
}
/**
* Triggered when the converter begins resolving a project.
*
* @param context The context object describing the current state the converter is in.
*/
private onBeginResolve(context: Context) {
const project = context.project;
if (this.readmeFile) {
project.readme = FS.readFileSync(this.readmeFile, 'utf-8');
}
if (this.packageFile) {
project.packageInfo = JSON.parse(FS.readFileSync(this.packageFile, 'utf-8'));
if (!project.name) {
project.name = `${project.packageInfo.name} - v${project.packageInfo.version}`;
}
}
}
}