chore(doc-gen): add TypeScript parsing
This commit is contained in:
parent
25a952755e
commit
9a72f19b97
|
@ -3,8 +3,8 @@
|
|||
|
||||
{% block body %}
|
||||
p.location-badge.
|
||||
exported from <a href="/{$ doc.moduleDoc.path $}">{$ doc.moduleDoc.id $}</a>
|
||||
defined in <a href="https://github.com/angular/angular/tree/master/modules/{$ doc.location.start.source.name $}.js#L{$ doc.location.start.line $}">{$ doc.location.start.source.name $}.js (line {$ doc.location.start.line $})</a>
|
||||
exported from {@link {$ doc.moduleDoc.id $} {$doc.moduleDoc.id $} }
|
||||
defined in <a href="https://github.com/angular/angular/tree/master/modules/{$ doc.fileInfo.relativePath $}#L{$ doc.location.start.line+1 $}-L{$ doc.location.end.line+1 $}">{$ doc.fileInfo.relativePath $} (line {$ doc.location.start.line+1 $})</a>
|
||||
|
||||
:markdown
|
||||
{$ doc.description | indent(2, true) $}
|
||||
|
@ -17,10 +17,10 @@ p.location-badge.
|
|||
.l-sub-section
|
||||
h3 {$ doc.constructorDoc.name $}
|
||||
|
||||
{% if doc.constructorDoc.params %}
|
||||
{% if doc.constructorDoc.parameters %}
|
||||
pre.prettyprint
|
||||
code.
|
||||
{$ doc.constructorDoc.name $}{$ paramList(doc.constructorDoc.params) | indent(4, true) | trim $}
|
||||
{$ doc.constructorDoc.name $}{$ paramList(doc.constructorDoc.parameters) | indent(4, true) | trim $}
|
||||
{% endif %}
|
||||
:markdown
|
||||
{$ doc.constructorDoc.description | indent(6, true) | replace('## Example', '') | replace('# Example', '') $}
|
||||
|
@ -32,10 +32,10 @@ p.location-badge.
|
|||
.l-sub-section
|
||||
h3 {$ member.name $}
|
||||
|
||||
{% if member.params %}
|
||||
{% if member.parameters %}
|
||||
pre.prettyprint
|
||||
code.
|
||||
{$ member.name $}{$ paramList(member.params) | indent(4, true) | trim $}
|
||||
{$ member.name $}{$ paramList(member.parameters) | indent(4, true) | trim $}{$ returnType(doc.returnType) $}
|
||||
{% endif %}
|
||||
:markdown
|
||||
|
||||
|
|
|
@ -5,10 +5,15 @@
|
|||
.l-main-section
|
||||
h2(class="function export") {$ doc.name $}
|
||||
|
||||
p <code>{$ paramList(doc.parameters) $}</code>
|
||||
{% if doc.parameters %}
|
||||
pre.prettyprint
|
||||
code.
|
||||
{$ doc.name $}{$ paramList(doc.parameters) | indent(4, true) | trim $}{$ returnType(doc.returnType) $}
|
||||
{% endif %}
|
||||
|
||||
p.location-badge.
|
||||
exported from <a href="/{$ doc.moduleDoc.path $}">{$ doc.moduleDoc.id $}</a>
|
||||
exported from {@link {$ doc.moduleDoc.id $} {$doc.moduleDoc.id $} }
|
||||
defined in <a href="https://github.com/angular/angular/tree/master/modules/{$ doc.fileInfo.relativePath $}#L{$ doc.location.start.line+1 $}-L{$ doc.location.end.line+1 $}">{$ doc.fileInfo.relativePath $} (line {$ doc.location.start.line+1 $})</a>
|
||||
|
||||
:markdown
|
||||
{$ doc.description | indent(4, true) $}
|
||||
|
|
|
@ -5,3 +5,8 @@
|
|||
{%- endfor %})
|
||||
{%- endif %}
|
||||
{%- endmacro -%}
|
||||
|
||||
|
||||
{% macro returnType(returnType) -%}
|
||||
{%- if returnType %} : {$ returnType | escape $}{% endif -%}
|
||||
{%- endmacro -%}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
{% extends 'layout/base.template.html' -%}
|
||||
{% block body -%}
|
||||
p.location-badge.
|
||||
defined in <a href="https://github.com/angular/angular/tree/master/modules/{$ doc.fileInfo.relativePath $}#L{$ doc.location.start.line+1 $}-L{$ doc.location.end.line+1 $}">{$ doc.fileInfo.relativePath $} (line {$ doc.location.start.line+1 $})</a>
|
||||
|
||||
ul
|
||||
for page, slug in public.docs[current.path[1]][current.path[2]][current.path[3]][current.path[4]]._data
|
||||
if slug != 'index'
|
||||
|
|
|
@ -15,6 +15,11 @@ module.exports = new Package('angular', [jsdocPackage, nunjucksPackage, linksPac
|
|||
|
||||
// Register the services and file readers
|
||||
.factory(require('./services/modules'))
|
||||
.factory(require('./services/tsParser'))
|
||||
.factory(require('./services/tsParser/createCompilerHost'))
|
||||
.factory(require('./services/tsParser/getFileInfo'))
|
||||
.factory(require('./services/tsParser/getExportDocType'))
|
||||
.factory(require('./services/tsParser/getContent'))
|
||||
.factory(require('./readers/ngdoc'))
|
||||
|
||||
.factory('EXPORT_DOC_TYPES', function() {
|
||||
|
@ -28,6 +33,7 @@ module.exports = new Package('angular', [jsdocPackage, nunjucksPackage, linksPac
|
|||
|
||||
|
||||
// Register the processors
|
||||
.processor(require('./processors/readTypeScriptModules'))
|
||||
.processor(require('./processors/generateNavigationDoc'))
|
||||
.processor(require('./processors/extractTitleFromGuides'))
|
||||
.processor(require('./processors/createOverviewDump'))
|
||||
|
@ -40,13 +46,23 @@ module.exports = new Package('angular', [jsdocPackage, nunjucksPackage, linksPac
|
|||
|
||||
|
||||
// Configure file reading
|
||||
.config(function(readFilesProcessor, ngdocFileReader) {
|
||||
.config(function(readFilesProcessor, ngdocFileReader, readTypeScriptModules) {
|
||||
readFilesProcessor.fileReaders = [ngdocFileReader];
|
||||
readFilesProcessor.basePath = path.resolve(__dirname, '../..');
|
||||
readFilesProcessor.sourceFiles = [
|
||||
{ include: 'modules/*/docs/**/*.md', basePath: 'modules' },
|
||||
{ include: 'docs/content/**/*.md', basePath: 'docs/content' }
|
||||
];
|
||||
|
||||
readTypeScriptModules.sourceFiles = [
|
||||
'*/*.js',
|
||||
'*/src/**/*.js',
|
||||
'*/*.es6',
|
||||
'*/src/**/*.es6',
|
||||
'*/*.ts',
|
||||
'*/src/**/*.ts'
|
||||
];
|
||||
readTypeScriptModules.basePath = 'modules';
|
||||
})
|
||||
|
||||
|
||||
|
@ -54,6 +70,14 @@ module.exports = new Package('angular', [jsdocPackage, nunjucksPackage, linksPac
|
|||
parseTagsProcessor.tagDefinitions.push(require('./tag-defs/public'));
|
||||
parseTagsProcessor.tagDefinitions.push(require('./tag-defs/private'));
|
||||
parseTagsProcessor.tagDefinitions.push(require('./tag-defs/exportedAs'));
|
||||
|
||||
// We actually don't want to parse param docs in this package as we are getting the data out using TS
|
||||
parseTagsProcessor.tagDefinitions.forEach(function(tagDef) {
|
||||
if (tagDef.name === 'param') {
|
||||
tagDef.ignore = true;
|
||||
}
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
@ -88,12 +112,6 @@ module.exports = new Package('angular', [jsdocPackage, nunjucksPackage, linksPac
|
|||
// Configure ids and paths
|
||||
.config(function(computeIdsProcessor, computePathsProcessor, EXPORT_DOC_TYPES) {
|
||||
|
||||
computeIdsProcessor.idTemplates.push({
|
||||
docTypes: EXPORT_DOC_TYPES,
|
||||
idTemplate: '${moduleDoc.id}.${name}',
|
||||
getAliases: function(doc) { return [doc.id, doc.name]; }
|
||||
});
|
||||
|
||||
computeIdsProcessor.idTemplates.push({
|
||||
docTypes: ['member'],
|
||||
idTemplate: '${classDoc.id}.${name}',
|
||||
|
@ -117,7 +135,7 @@ module.exports = new Package('angular', [jsdocPackage, nunjucksPackage, linksPac
|
|||
|
||||
computePathsProcessor.pathTemplates.push({
|
||||
docTypes: ['module'],
|
||||
pathTemplate: '${id}',
|
||||
pathTemplate: '/${id}',
|
||||
outputPathTemplate: MODULES_DOCS_PATH + '/${id}/index.html'
|
||||
});
|
||||
|
||||
|
@ -136,7 +154,7 @@ module.exports = new Package('angular', [jsdocPackage, nunjucksPackage, linksPac
|
|||
|
||||
computePathsProcessor.pathTemplates.push({
|
||||
docTypes: ['guide'],
|
||||
pathTemplate: '${id}',
|
||||
pathTemplate: '/${id}',
|
||||
outputPathTemplate: GUIDES_PATH + '/${id}.html'
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
export var x = 100;
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* @module
|
||||
* @description
|
||||
* This is the module description
|
||||
*/
|
||||
|
||||
export * from 'importedSrc';
|
||||
|
||||
/**
|
||||
* This is some random other comment
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is MyClass
|
||||
*/
|
||||
export class MyClass {
|
||||
message: String;
|
||||
|
||||
/**
|
||||
* Create a new MyClass
|
||||
* @param {String} name The name to say hello to
|
||||
*/
|
||||
constructor(name) {
|
||||
this.message = 'hello ' + name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a greeting message
|
||||
*/
|
||||
greet() {
|
||||
return this.message;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An exported function
|
||||
*/
|
||||
export var myFn = (val:number) => { return val*2; }
|
|
@ -0,0 +1,201 @@
|
|||
var glob = require('glob');
|
||||
var path = require('canonical-path');
|
||||
var _ = require('lodash');
|
||||
var ts = require('typescript');
|
||||
|
||||
module.exports = function readTypeScriptModules(tsParser, readFilesProcessor, modules, getFileInfo, getExportDocType, getContent, log) {
|
||||
|
||||
return {
|
||||
$runAfter: ['files-read'],
|
||||
$runBefore: ['parsing-tags'],
|
||||
|
||||
$validate: {
|
||||
sourceFiles: {presence: true},
|
||||
basePath: {presence: true},
|
||||
hidePrivateMembers: { inclusion: [true, false] },
|
||||
hideSpecialExports: { inclusion: [true, false] }
|
||||
},
|
||||
|
||||
sourceFiles: [],
|
||||
basePath: '.',
|
||||
hidePrivateMembers: false,
|
||||
hideSpecialExports: true,
|
||||
|
||||
$process: function(docs) {
|
||||
|
||||
var hideSpecialExports = this.hideSpecialExports;
|
||||
var hidePrivateMembers = this.hidePrivateMembers;
|
||||
|
||||
var basePath = path.resolve(readFilesProcessor.basePath, this.basePath);
|
||||
var filesPaths = expandSourceFiles(this.sourceFiles, basePath);
|
||||
var parseInfo = tsParser.parse(filesPaths, this.basePath);
|
||||
var moduleSymbols = parseInfo.moduleSymbols;
|
||||
|
||||
// Iterate through each of the modules that were parsed and generate a module doc
|
||||
// as well as docs for each module's exports.
|
||||
moduleSymbols.forEach(function(moduleSymbol) {
|
||||
|
||||
var moduleDoc = createModuleDoc(moduleSymbol, basePath);
|
||||
|
||||
// Add this module doc to the module lookup collection and the docs collection
|
||||
modules[moduleDoc.id] = moduleDoc;
|
||||
docs.push(moduleDoc);
|
||||
|
||||
// Iterate through this module's exports and generate a doc for each
|
||||
moduleSymbol.exportArray.forEach(function(exportSymbol) {
|
||||
|
||||
// Ignore exports starting with an underscore
|
||||
if (hideSpecialExports && exportSymbol.name.charAt(0) === '_') return;
|
||||
|
||||
// If the symbol is an Alias then for most things we want the original resolved symbol
|
||||
var resolvedExport = exportSymbol.resolvedSymbol || exportSymbol;
|
||||
var exportDoc = createExportDoc(exportSymbol.name, resolvedExport, moduleDoc, basePath, parseInfo.typeChecker);
|
||||
log.debug('>>>> EXPORT: ' + exportDoc.name + ' (' + exportDoc.docType + ') from ' + moduleDoc.id);
|
||||
|
||||
// Generate docs for each of the export's members
|
||||
if (resolvedExport.flags & ts.SymbolFlags.HasMembers) {
|
||||
|
||||
exportDoc.members = [];
|
||||
for(var memberName in resolvedExport.members) {
|
||||
log.silly('>>>>>> member: ' + memberName + ' from ' + exportDoc.id + ' in ' + moduleDoc.id);
|
||||
var memberSymbol = resolvedExport.members[memberName];
|
||||
var memberDoc = createMemberDoc(memberSymbol, exportDoc, basePath, parseInfo.typeChecker);
|
||||
|
||||
// We special case the constructor and sort the other members alphabetically
|
||||
if (memberSymbol.flags & ts.SymbolFlags.Constructor) {
|
||||
exportDoc.constructorDoc = memberDoc;
|
||||
docs.push(memberDoc);
|
||||
} else if (!hidePrivateMembers || memberSymbol.name.charAt(0) !== '_') {
|
||||
docs.push(memberDoc);
|
||||
insertSorted(exportDoc.members, memberDoc, 'name');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add this export doc to its module doc
|
||||
moduleDoc.exports.push(exportDoc);
|
||||
docs.push(exportDoc);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function createModuleDoc(moduleSymbol, basePath) {
|
||||
var id = moduleSymbol.name.replace(/^"|"$/g, '');
|
||||
var moduleDoc = {
|
||||
docType: 'module',
|
||||
id: id,
|
||||
aliases: [id],
|
||||
moduleTree: moduleSymbol,
|
||||
content: getContent(moduleSymbol),
|
||||
exports: [],
|
||||
fileInfo: getFileInfo(moduleSymbol, basePath),
|
||||
location: getLocation(moduleSymbol)
|
||||
};
|
||||
return moduleDoc;
|
||||
}
|
||||
|
||||
function createExportDoc(name, exportSymbol, moduleDoc, basePath, typeChecker) {
|
||||
var exportDoc = {
|
||||
docType: getExportDocType(exportSymbol),
|
||||
name: name,
|
||||
id: name,
|
||||
aliases: [name],
|
||||
moduleDoc: moduleDoc,
|
||||
content: getContent(exportSymbol),
|
||||
fileInfo: getFileInfo(exportSymbol, basePath),
|
||||
location: getLocation(exportSymbol)
|
||||
};
|
||||
if(exportSymbol.flags & ts.SymbolFlags.Function) {
|
||||
exportDoc.parameters = getParameters(typeChecker, exportSymbol);
|
||||
exportDoc.returnType = getReturnType(typeChecker, exportSymbol);
|
||||
}
|
||||
return exportDoc;
|
||||
}
|
||||
|
||||
function createMemberDoc(memberSymbol, classDoc, basePath, typeChecker) {
|
||||
var memberDoc = {
|
||||
docType: 'member',
|
||||
classDoc: classDoc,
|
||||
name: memberSymbol.name,
|
||||
id: memberSymbol.name,
|
||||
content: getContent(memberSymbol),
|
||||
fileInfo: getFileInfo(memberSymbol, basePath),
|
||||
location: getLocation(memberSymbol)
|
||||
};
|
||||
|
||||
if (memberSymbol.flags & ts.SymbolFlags.Method) {
|
||||
// NOTE: we use the property name `parameters` here so we don't conflict
|
||||
// with the `params` property that will be updated by dgeni reading the
|
||||
// `@param` tags from the docs
|
||||
memberDoc.parameters = getParameters(typeChecker, memberSymbol);
|
||||
memberDoc.returnType = getReturnType(typeChecker, memberSymbol);
|
||||
}
|
||||
|
||||
if (memberSymbol.flags & ts.SymbolFlags.Constructor) {
|
||||
memberDoc.parameters = getParameters(typeChecker, memberSymbol);
|
||||
memberDoc.name = 'constructor';
|
||||
}
|
||||
|
||||
return memberDoc;
|
||||
}
|
||||
|
||||
|
||||
function getParameters(typeChecker, symbol) {
|
||||
var declaration = symbol.valueDeclaration || symbol.declarations[0];
|
||||
var sourceFile = ts.getSourceFileOfNode(declaration);
|
||||
if(!declaration.parameters) {
|
||||
console.log(declaration);
|
||||
throw 'missing declaration parameters';
|
||||
}
|
||||
var signature = typeChecker.getSignatureFromDeclaration(declaration);
|
||||
return declaration.parameters.map(function(parameter) {
|
||||
return getText(sourceFile, parameter).trim();
|
||||
});
|
||||
}
|
||||
|
||||
function getReturnType(typeChecker, symbol) {
|
||||
var declaration = symbol.valueDeclaration || symbol.declarations[0];
|
||||
var sourceFile = ts.getSourceFileOfNode(declaration);
|
||||
if(declaration.type) {
|
||||
var signature = typeChecker.getSignatureFromDeclaration(declaration);
|
||||
return getText(sourceFile, declaration.type).trim();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function expandSourceFiles(sourceFiles, basePath) {
|
||||
var filePaths = [];
|
||||
sourceFiles.forEach(function(sourcePattern) {
|
||||
filePaths = filePaths.concat(glob.sync(sourcePattern, { cwd: basePath }));
|
||||
});
|
||||
return filePaths;
|
||||
}
|
||||
|
||||
|
||||
function getText(sourceFile, node) {
|
||||
return sourceFile.text.substring(node.pos, node.end);
|
||||
}
|
||||
|
||||
|
||||
function getLocation(symbol) {
|
||||
var node = symbol.valueDeclaration || symbol.declarations[0];
|
||||
var sourceFile = ts.getSourceFileOfNode(node);
|
||||
var location = {
|
||||
start: ts.getLineAndCharacterOfPosition(sourceFile, node.pos),
|
||||
end: ts.getLineAndCharacterOfPosition(sourceFile, node.end)
|
||||
};
|
||||
return location;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
function insertSorted(collection, item, property) {
|
||||
var index = collection.length;
|
||||
while(index>0) {
|
||||
if(collection[index-1][property] < item[property]) break;
|
||||
index -= 1;
|
||||
}
|
||||
collection.splice(index, 0, item);
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
var ts = require('typescript');
|
||||
|
||||
module.exports = function tsParser(createCompilerHost, log) {
|
||||
|
||||
return {
|
||||
|
||||
options: {
|
||||
allowNonTsExtensions: true
|
||||
},
|
||||
|
||||
parse: function(fileNames, baseDir) {
|
||||
// This is the easiest way I could find to ensure that we loaded
|
||||
// modules with paths relative to the baseDir
|
||||
process.chdir(baseDir);
|
||||
|
||||
// "Compile" a program from the given module filenames, to get hold of a
|
||||
// typeChecker that can be used to interrogate the modules, exports and so on.
|
||||
var host = createCompilerHost(this.options);
|
||||
var program = ts.createProgram(fileNames, this.options, host);
|
||||
var typeChecker = program.getTypeChecker();
|
||||
|
||||
// Create an array of module symbols for each file we were given
|
||||
var moduleSymbols = [];
|
||||
fileNames.forEach(function(fileName) {
|
||||
var sourceFile = program.getSourceFile(fileName);
|
||||
|
||||
if (!sourceFile) {
|
||||
throw new Error('Invalid source file: ' + fileName);
|
||||
} else if (!sourceFile.symbol) {
|
||||
// Some files contain only a comment and no actual module code
|
||||
log.warn('No module code found in ' + fileName);
|
||||
} else {
|
||||
moduleSymbols.push(sourceFile.symbol);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
moduleSymbols.forEach(function(tsModule) {
|
||||
|
||||
// The type checker has a nice helper function that returns an array of Symbols
|
||||
// representing the exports for a given module
|
||||
tsModule.exportArray = typeChecker.getExportsOfModule(tsModule);
|
||||
|
||||
// Although 'star' imports (e.g. `export * from 'some/module';) get resolved automatically
|
||||
// by the compiler/binder, it seems that explicit imports (e.g. `export {SomeClass} from 'some/module'`)
|
||||
// do not so we have to do a little work.
|
||||
tsModule.exportArray.forEach(function(moduleExport) {
|
||||
if (moduleExport.flags & 8388608 /* Alias */) {
|
||||
// To maintain the alias information (particularly the alias name)
|
||||
// we just attach the original "resolved" symbol to the alias symbol
|
||||
moduleExport.resolvedSymbol = typeChecker.getAliasedSymbol(moduleExport);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
moduleSymbols.typeChecker = typeChecker;
|
||||
|
||||
return {
|
||||
moduleSymbols: moduleSymbols,
|
||||
typeChecker: typeChecker,
|
||||
program: program,
|
||||
host: host
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
};
|
|
@ -0,0 +1,21 @@
|
|||
var mockPackage = require('../mocks/mockPackage');
|
||||
var Dgeni = require('dgeni');
|
||||
var path = require('canonical-path');
|
||||
|
||||
describe('tsParser', function() {
|
||||
var dgeni, injector, parser;
|
||||
|
||||
beforeEach(function() {
|
||||
dgeni = new Dgeni([mockPackage()]);
|
||||
injector = dgeni.configureInjector();
|
||||
parser = injector.get('tsParser');
|
||||
});
|
||||
|
||||
it("should parse a TS file", function() {
|
||||
var parseInfo = parser.parse(['testSrc.ts'], path.resolve(__dirname, '../mocks/'));
|
||||
var tsModules = parseInfo.moduleSymbols;
|
||||
expect(tsModules.length).toEqual(1);
|
||||
expect(tsModules[0].exportArray.length).toEqual(3);
|
||||
expect(tsModules[0].exportArray.map(function(i) { return i.name; })).toEqual(['MyClass', 'myFn', 'x']);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,32 @@
|
|||
var ts = require('typescript');
|
||||
|
||||
// These are the extension that we should consider when trying to load a module
|
||||
var extensions = ['.ts', '.js', '.es6']
|
||||
|
||||
// We need to provide our own version of CompilerHost because, at the moment, there is
|
||||
// a mix of `.ts`, `.es6` and `.js` (atScript) files in the project and the TypeScript
|
||||
// compiler only looks for `.ts` files when trying to load imports.
|
||||
module.exports = function createCompilerHost(log) {
|
||||
return function createCompilerHost(options) {
|
||||
|
||||
var host = ts.createCompilerHost(options);
|
||||
|
||||
// Override the `getSourceFile` implementation to also look for js and es6 files
|
||||
var getSourceFile = host.getSourceFile;
|
||||
host.getSourceFile = function(filename, languageVersion, onError) {
|
||||
// Iterate through each possible extension and return the first source file that is actually found
|
||||
for(var i=0; i<extensions.length; i++) {
|
||||
var extension = extensions[i];
|
||||
var altFileName = filename.replace(/\.ts$/, extension);
|
||||
log.silly('getSourceFile:', altFileName);
|
||||
var sourceFile = getSourceFile.call(host, altFileName, languageVersion, onError);
|
||||
if(sourceFile) {
|
||||
log.debug('found source file:', altFileName);
|
||||
return sourceFile;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return host;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,49 @@
|
|||
var ts = require('typescript');
|
||||
var LEADING_STAR = /^[^\S\r\n]*\*[^\S\n\r]?/gm;
|
||||
|
||||
module.exports = function getContent() {
|
||||
return function(symbol) {
|
||||
|
||||
var content = "";
|
||||
|
||||
if (!symbol.declarations) return content;
|
||||
|
||||
symbol.declarations.forEach(function(declaration) {
|
||||
|
||||
// If this is left side of dotted module declaration, there is no doc comment associated with this declaration
|
||||
if (declaration.kind === ts.SyntaxKind.ModuleDeclaration && declaration.body.kind === ts.SyntaxKind.ModuleDeclaration) {
|
||||
return content;
|
||||
}
|
||||
|
||||
// If this is dotted module name, get the doc comments from the parent
|
||||
while (declaration.kind === ts.SyntaxKind.ModuleDeclaration && declaration.parent.kind === ts.SyntaxKind.ModuleDeclaration) {
|
||||
declaration = declaration.parent;
|
||||
}
|
||||
|
||||
// If this is a variable declaration then we get the doc comments from the grand parent
|
||||
if (declaration.kind === ts.SyntaxKind.VariableDeclaration) {
|
||||
declaration = declaration.parent.parent;
|
||||
}
|
||||
|
||||
// Get the source file of this declaration
|
||||
var sourceFile = ts.getSourceFileOfNode(declaration);
|
||||
var commentRanges = ts.getJsDocComments(declaration, sourceFile);
|
||||
|
||||
if (commentRanges) {
|
||||
commentRanges.forEach(function(commentRange) {
|
||||
content += sourceFile.text
|
||||
.substring(commentRange.pos+ '/**'.length, commentRange.end - '*/'.length)
|
||||
.replace(LEADING_STAR, '')
|
||||
.trim()
|
||||
if (commentRange.hasTrailingNewLine) {
|
||||
content += '\n';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
content += '\n';
|
||||
});
|
||||
|
||||
return content;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,46 @@
|
|||
var ts = require('typescript');
|
||||
|
||||
module.exports = function getExportDocType() {
|
||||
|
||||
return function(symbol) {
|
||||
if(symbol.flags & ts.SymbolFlags.FunctionScopedVariable) {
|
||||
return 'var';
|
||||
}
|
||||
if(symbol.flags & ts.SymbolFlags.BlockScopedVariable) {
|
||||
return getBlockScopedVariableDocType(symbol);
|
||||
}
|
||||
if(symbol.flags & ts.SymbolFlags.Function) {
|
||||
return 'function';
|
||||
}
|
||||
if(symbol.flags & ts.SymbolFlags.Class) {
|
||||
return 'class';
|
||||
}
|
||||
if(symbol.flags & ts.SymbolFlags.Interface) {
|
||||
return 'interface';
|
||||
}
|
||||
if(symbol.flags & ts.SymbolFlags.ConstEnum) {
|
||||
return 'enum';
|
||||
}
|
||||
if(symbol.flags & ts.SymbolFlags.RegularEnum) {
|
||||
return 'enum';
|
||||
}
|
||||
if(symbol.flags & ts.SymbolFlags.Property) {
|
||||
return 'module-property';
|
||||
}
|
||||
|
||||
log.warn('Unknown symbol type', symbol.name, symbol.flags, symbol.target);
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
function getBlockScopedVariableDocType(symbol) {
|
||||
|
||||
var node = symbol.valueDeclaration;
|
||||
while(node) {
|
||||
if ( node.flags & 0x2000 /* const */) {
|
||||
return 'const';
|
||||
}
|
||||
node = node.parent;
|
||||
}
|
||||
return 'let';
|
||||
}
|
||||
};
|
|
@ -0,0 +1,20 @@
|
|||
var path = require('canonical-path');
|
||||
var ts = require('typescript');
|
||||
|
||||
module.exports = function getFileInfo(log) {
|
||||
|
||||
return function (symbol, basePath) {
|
||||
var fileName = ts.getSourceFileOfNode(symbol.declarations[0]).fileName;
|
||||
|
||||
var file = path.resolve(basePath, fileName);
|
||||
var fileInfo = {
|
||||
filePath: file,
|
||||
baseName: path.basename(file, path.extname(file)),
|
||||
extension: path.extname(file).replace(/^\./, ''),
|
||||
basePath: basePath,
|
||||
relativePath: fileName,
|
||||
projectRelativePath: fileName
|
||||
};
|
||||
return fileInfo;
|
||||
};
|
||||
};
|
|
@ -4,7 +4,8 @@
|
|||
{% block body %}
|
||||
<h1 class="class export">{$ doc.name $} <span class="type">class</span></h1>
|
||||
<p class="module">exported from <a href="/{$ doc.moduleDoc.path $}">{$ doc.moduleDoc.id $}</a><br/>
|
||||
defined in <a href="https://github.com/angular/angular/tree/master/modules/{$ doc.location.start.source.name $}.js#L{$ doc.location.start.line $}">{$ doc.location.start.source.name $}.js (line {$ doc.location.start.line $})</a></p>
|
||||
defined in <a href="https://github.com/angular/angular/tree/master/modules/{$ doc.fileInfo.relativePath $}#L{$ doc.location.start.line+1 $}-L{$ doc.location.end.line+1 $}">
|
||||
{$ doc.fileInfo.relativePath $} (line {$ doc.location.start.line+1 $})</a></p>
|
||||
<p>{$ doc.description | marked $}</p>
|
||||
|
||||
{%- if doc.constructorDoc or doc.members.length -%}
|
||||
|
|
|
@ -3,6 +3,25 @@ var basePackage = require('../dgeni-package');
|
|||
|
||||
module.exports = new Package('angular-public', [basePackage])
|
||||
|
||||
.config(function(readTypeScriptModules) {
|
||||
readTypeScriptModules.sourceFiles = [
|
||||
'angular2/annotations.js',
|
||||
'angular2/change_detection.ts',
|
||||
'angular2/core.js',
|
||||
'angular2/di.ts',
|
||||
'angular2/directives.js',
|
||||
'angular2/forms.js',
|
||||
'angular2/router.js',
|
||||
'angular2/test.js',
|
||||
'angular2/pipes.js'
|
||||
];
|
||||
readTypeScriptModules.hidePrivateMembers = true;
|
||||
})
|
||||
|
||||
.config(function(getLinkInfo) {
|
||||
getLinkInfo.useFirstAmbiguousLink = false;
|
||||
})
|
||||
|
||||
// Configure file writing
|
||||
.config(function(writeFilesProcessor) {
|
||||
writeFilesProcessor.outputFolder = 'dist/public_docs';
|
||||
|
|
Loading…
Reference in New Issue