/
Plugin.js
115 lines (91 loc) · 3.78 KB
/
Plugin.js
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
const
fs = require('fs'),
glob = require('glob'),
mkdirp = require('mkdirp'),
path = require('path'),
rimraf = require('rimraf');
class Plugin {
constructor() {
this._enable = true;
this._destination = undefined;
this._externalImports = [];
}
onStart(ev) {
if (!ev.data.option) return;
if ('enable' in ev.data.option) this._enable = ev.data.option.enable;
}
onHandleConfig(ev) {
if (!this._enable) return;
this._source = ev.data.config.source;
this._destination = ev.data.config.destination;
const createATempImportsFile = (pattern, mapper) => (pathToExports) => {
const matched = pathToExports.match(pattern);
const importsFileName = `.imports-from-${mapper(matched)}.js`;
const destination = path.join(this._source, importsFileName);
this._externalImports.push(destination);
fs.copyFileSync(pathToExports, path.resolve(destination));
}
// @serenity-js/* modules
glob.sync(ev.data.option.externals)
.forEach(createATempImportsFile(/@(serenity-js)\/(.*?)\//, m => `${ m[1] }-${ m[2] }`));
// any external modules with type definitions under resources
glob.sync(path.resolve(__dirname, '../resources/*.js'))
.forEach(createATempImportsFile(/external\.(.*?)\.js/, m => `${ m[1] }`));
}
onHandleDocs(event) {
// remove temp files
this._externalImports.forEach(pathToExternalImportsFile => {
rimraf.sync(pathToExternalImportsFile);
const tagIndex = event.data.docs.findIndex(doc =>
doc.kind === 'file' && doc.name === pathToExternalImportsFile,
);
event.data.docs.splice(tagIndex, 1);
});
/*
* Mark as `builtinExternal` so that they're not parsed again by the SourceDocBuilder
* see https://github.com/esdoc/esdoc-plugins/blob/master/esdoc-external-ecmascript-plugin/src/Plugin.js#L18
*/
for (const doc of event.data.docs) {
if (doc.kind === 'external' && this._externalImports.includes(doc.memberof)) {
doc.builtinExternal = true;
}
}
const exported = {};
for (const doc of event.data.docs) {
if (! (isImportable(doc) && belongsToSerenityJS(doc))) {
continue;
}
const
module = moduleNameFrom(doc.importPath),
id = `${doc.importPath}~${doc.name}`,
pathToDocs = doc.kind !== 'function'
? `/modules/${ module }/${ doc.kind }/${ doc.longname }.html`
: `/modules/${ module }/${ doc.kind }/index.html#static-function-${ doc.name }`;
exported[module] = exported[module] || [];
exported[module].push({
id,
pathToDocs,
})
}
for (const module of Object.keys(exported)) {
mkdirp.sync(this._destination);
fs.writeFileSync(path.resolve(this._destination, 'exported.json'), JSON.stringify(exported[module], null, 4));
fs.writeFileSync(path.resolve(this._destination, 'exported.js'), exported[module].map(doc =>
`/** @external {${ doc.id }} ${ doc.pathToDocs } */`
).join('\n'));
}
}
}
function moduleNameFrom(importPath) {
return importPath.match(/@serenity-js\/([\w]+)/)[1];
}
function belongsToSerenityJS(doc) {
return doc.importPath
&& doc.importPath.startsWith('@serenity-js');
}
function isImportable(doc) {
return !! doc.export
&& !! doc.importPath
&& (doc.access === 'public' || doc.access === 'protected' || ! doc.access);
}
module.exports = new Plugin();