Use jsdoc-plugin-typescript

This commit is contained in:
ahocevar
2018-10-29 15:24:12 +01:00
parent e239eb338f
commit b50749e1ea
10 changed files with 15 additions and 170 deletions

View File

@@ -15,16 +15,15 @@
},
"plugins": [
"config/jsdoc/api/plugins/markdown",
"config/jsdoc/typescript-plugin",
"config/jsdoc/api/plugins/normalize-longnames",
"jsdoc-plugin-typescript",
"config/jsdoc/api/plugins/inline-options",
"config/jsdoc/api/plugins/inheritdoc",
"config/jsdoc/api/plugins/events",
"config/jsdoc/api/plugins/observable",
"config/jsdoc/api/plugins/api"
],
"markdown": {
"parser": "gfm"
"typescript": {
"moduleRoot": "src"
},
"templates": {
"cleverLinks": true,

View File

@@ -34,7 +34,7 @@ Interactions for [vector features](module-ol_Feature-Feature.html)
<tr><th>Projections</th><th>Observable objects</th><th>Other components</th></tr>
<tr><td><p>All coordinates and extents need to be provided in view projection (default: EPSG:3857). To transform, use [ol/proj#transform()](module-ol_proj.html#.transform) and [ol/proj#transformExtent()](module-ol_proj.html#.transformExtent).</p>
[ol/proj](module-ol_proj.html)</td>
<td><p>Changes to all [ol/Object](module-ol_Object-BaseObject.html)s can be observed by calling the [object.on('propertychange')](module-ol_Object-BaseObject.html#on) method. Listeners receive an [ol/Object~ObjectEvent](module-ol_Object-ObjectEvent.html) with information on the changed property and old value.</p>
<td><p>Changes to all [ol/Object](module-ol_Object-BaseObject.html)s can be observed by calling the [object.on('propertychange')](module-ol_Object-BaseObject.html#on) method. Listeners receive an [ol/Object.ObjectEvent](module-ol_Object-ObjectEvent.html) with information on the changed property and old value.</p>
<td>
[ol/Geolocation](module-ol_Geolocation.html)<br>
[ol/Overlay](module-ol_Overlay-Overlay.html)<br></td>

View File

@@ -102,6 +102,8 @@ exports.handlers = {
modules[doclet.longname.split(/[~\.]/).shift()] = true;
if (!(doclet.longname in classes)) {
classes[doclet.longname] = doclet;
} else if ('augments' in doclet) {
classes[doclet.longname].augments = doclet.augments;
}
}
if (doclet.name === doclet.longname && !doclet.memberof) {

View File

@@ -1,21 +0,0 @@
/**
* @filedesc
* Normalize module path to make no distinction between static and member at
* the module level.
*/
exports.handlers = {
/**
* Adds default export to module path types without name
* @param {Object} e Event object.
*/
newDoclet: function(e) {
const doclet = e.doclet;
const module = doclet.longname.split('#').shift();
if (module.indexOf('module:') == 0 && module.indexOf('.') !== -1) {
doclet.longname = doclet.longname.replace(module, module.replace('.', '~'));
}
}
};

View File

@@ -47,7 +47,7 @@ exports.handlers = {
if (!cls.fires) {
cls.fires = [];
}
event = 'module:ol/Object~ObjectEvent#event:change:' + name;
event = 'module:ol/Object.ObjectEvent#event:change:' + name;
if (cls.fires.indexOf(event) == -1) {
cls.fires.push(event);
}

View File

@@ -77,7 +77,7 @@ var self = this;
(<?js= self.linkto(eventClass.longname) ?>)
<?js } ?>
<?js } ?>
<?js= self.partial('stability.tmpl', eventDoclet || (data.stability ? data : {stability: 'experimental'})) ?>
<?js= self.partial('stability.tmpl', eventDoclet || (data.stability ? data : {})) ?>
<?js if (description) { ?> -
<?js= description ?>
<?js } ?>

View File

@@ -8,7 +8,7 @@
<th>Name</th>
<th>Type</th>
<th>Settable</th>
<th><a href="module-ol_Object-ObjectEvent.html">ol/Object~ObjectEvent</a> type</th>
<th><a href="module-ol_Object-ObjectEvent.html">ol/Object.ObjectEvent</a> type</th>
<th class="last">Description</th>
</tr>
</thead>

View File

@@ -10,9 +10,12 @@
"includePattern": "\\.js$"
},
"plugins": [
"config/jsdoc/typescript-plugin",
"jsdoc-plugin-typescript",
"config/jsdoc/info/api-plugin",
"config/jsdoc/info/define-plugin",
"config/jsdoc/info/virtual-plugin"
]
],
"typescript": {
"moduleRoot": "src"
}
}

View File

@@ -1,139 +0,0 @@
const path = require('path');
const fs = require('fs');
const importRegEx = /(typeof )?import\("([^"]*)"\)\.([^ \.\|\}><,\)=\n]*)([ \.\|\}><,\)=\n])/g;
const typedefRegEx = /@typedef \{[^\}]*\} ([^ \r?\n?]*)/;
const defaultExports = {};
const fileNodes = {};
function getDefaultExportName(moduleId, parser) {
if (!defaultExports[moduleId]) {
if (!fileNodes[moduleId]) {
const classDeclarations = {};
const absolutePath = path.join(process.cwd(), 'src', moduleId + '.js');
const file = fs.readFileSync(absolutePath, 'UTF-8');
const node = fileNodes[moduleId] = parser.astBuilder.build(file, absolutePath);
if (node.program && node.program.body) {
const nodes = node.program.body;
for (let i = 0, ii = nodes.length; i < ii; ++i) {
const node = nodes[i];
if (node.type === 'ClassDeclaration') {
classDeclarations[node.id.name] = node;
} else if (node.type === 'ExportDefaultDeclaration') {
const classDeclaration = classDeclarations[node.declaration.name];
if (classDeclaration) {
defaultExports[moduleId] = classDeclaration.id.name;
}
}
}
}
}
}
if (!defaultExports[moduleId]) {
defaultExports[moduleId] = '';
}
return defaultExports[moduleId];
}
exports.astNodeVisitor = {
visitNode: function(node, e, parser, currentSourceName) {
if (node.type === 'File') {
const modulePath = path.relative(path.join(process.cwd(), 'src'), currentSourceName).replace(/\.js$/, '');
fileNodes[modulePath] = node;
const identifiers = {};
if (node.program && node.program.body) {
const nodes = node.program.body;
for (let i = 0, ii = nodes.length; i < ii; ++i) {
let node = nodes[i];
if (node.type === 'ExportNamedDeclaration' && node.declaration) {
node = node.declaration;
}
if (node.type === 'ImportDeclaration') {
node.specifiers.forEach(specifier => {
let defaultImport = false;
switch (specifier.type) {
case 'ImportDefaultSpecifier':
defaultImport = true;
// fallthrough
case 'ImportSpecifier':
identifiers[specifier.local.name] = {
defaultImport,
value: node.source.value
};
break;
default:
}
});
} else if (node.type === 'ClassDeclaration') {
if (node.id && node.id.name) {
identifiers[node.id.name] = {
value: path.basename(currentSourceName)
};
}
// Add class inheritance information because JSDoc does not honor
// the ES6 class's `extends` keyword
if (node.superClass && node.leadingComments) {
const leadingComment = node.leadingComments[node.leadingComments.length - 1];
const lines = leadingComment.value.split(/\r?\n/);
lines.push(lines[lines.length - 1]);
const identifier = identifiers[node.superClass.name];
if (identifier) {
const absolutePath = path.resolve(path.dirname(currentSourceName), identifier.value);
const moduleId = path.relative(path.join(process.cwd(), 'src'), absolutePath).replace(/\.js$/, '');
const exportName = identifier.defaultImport ? getDefaultExportName(moduleId, parser) : node.superClass.name;
lines[lines.length - 2] = ' * @extends ' + `module:${moduleId}${exportName ? '~' + exportName : ''}`;
} else {
lines[lines.length - 2] = ' * @extends ' + node.superClass.name;
}
leadingComment.value = lines.join('\n');
}
}
}
}
if (node.comments) {
node.comments.forEach(comment => {
//TODO Handle typeof, to indicate that a constructor instead of an
// instance is needed.
comment.value = comment.value.replace(/typeof /g, '');
// Convert `import("path/to/module").export` to
// `module:path/to/module~Name`
let importMatch;
while ((importMatch = importRegEx.exec(comment.value))) {
importRegEx.lastIndex = 0;
const rel = path.resolve(path.dirname(currentSourceName), importMatch[2]);
const importModule = path.relative(path.join(process.cwd(), 'src'), rel).replace(/\.js$/, '');
const exportName = importMatch[3] === 'default' ? getDefaultExportName(importModule, parser) : importMatch[3];
const replacement = `module:${importModule}${exportName ? '~' + exportName : ''}`;
comment.value = comment.value.replace(importMatch[0], replacement + importMatch[4]);
}
// Treat `@typedef`s like named exports
const typedefMatch = comment.value.replace(/\r?\n?\s*\*\s/g, ' ').match(typedefRegEx);
if (typedefMatch) {
identifiers[typedefMatch[1]] = {
value: path.basename(currentSourceName)
};
}
// Replace local types with the full `module:` path
Object.keys(identifiers).forEach(key => {
const regex = new RegExp(`(@fires |[\{<\|,] ?)${key}`, 'g');
if (regex.test(comment.value)) {
const identifier = identifiers[key];
const absolutePath = path.resolve(path.dirname(currentSourceName), identifier.value);
const moduleId = path.relative(path.join(process.cwd(), 'src'), absolutePath).replace(/\.js$/, '');
const exportName = identifier.defaultImport ? getDefaultExportName(moduleId, parser) : key;
comment.value = comment.value.replace(regex, '$1' + `module:${moduleId}${exportName ? '~' + exportName : ''}`);
}
});
});
}
}
}
};

View File

@@ -60,6 +60,7 @@
"istanbul": "0.4.5",
"jquery": "3.3.1",
"jsdoc": "3.5.5",
"jsdoc-plugin-typescript": "^1.0.2",
"karma": "^3.0.0",
"karma-chrome-launcher": "2.2.0",
"karma-coverage": "^1.1.1",