api-templates: extract and render directive info distinct from classes
Closes #221
This commit is contained in:
parent
b176f42302
commit
e0f5261d3b
|
@ -7,6 +7,9 @@ module.exports = new Package('angular.io', [basePackage])
|
|||
.factory(require('./services/renderMarkdown'))
|
||||
.processor(require('./processors/addJadeDataDocsProcessor'))
|
||||
.processor(require('./processors/filterUnwantedDecorators'))
|
||||
.processor(require('./processors/extractDirectiveClasses'))
|
||||
.processor(require('./processors/matchUpDirectiveDecorators'))
|
||||
|
||||
// overrides base packageInfo and returns the one for the 'angular/angular' repo.
|
||||
.factory(require('./services/packageInfo'))
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
var _ = require('lodash');
|
||||
|
||||
module.exports = function extractDirectiveClassesProcessor(EXPORT_DOC_TYPES) {
|
||||
|
||||
// Add the "directive" docType into those that can be exported from a module
|
||||
EXPORT_DOC_TYPES.push('directive');
|
||||
|
||||
return {
|
||||
$runAfter: ['processing-docs'],
|
||||
$runBefore: ['docs-processed'],
|
||||
decoratorTypes: ['Directive', 'Component', 'View'],
|
||||
$process: function(docs) {
|
||||
var decoratorTypes = this.decoratorTypes;
|
||||
|
||||
_.forEach(docs, function(doc) {
|
||||
|
||||
_.forEach(doc.decorators, function(decorator) {
|
||||
|
||||
if (decoratorTypes.indexOf(decorator.name) !== -1) {
|
||||
doc.docType = 'directive';
|
||||
|
||||
doc[decorator.name.toLowerCase() + 'Options'] = decorator.argumentInfo[0];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return docs;
|
||||
}
|
||||
};
|
||||
};
|
|
@ -0,0 +1,51 @@
|
|||
var mockPackage = require('../mocks/mockPackage');
|
||||
var Dgeni = require('dgeni');
|
||||
|
||||
describe('extractDirectiveClasses processor', function() {
|
||||
var dgeni, injector, processor;
|
||||
|
||||
beforeEach(function() {
|
||||
dgeni = new Dgeni([mockPackage()]);
|
||||
injector = dgeni.configureInjector();
|
||||
processor = injector.get('extractDirectiveClassesProcessor');
|
||||
});
|
||||
|
||||
it('should extract specified decorator arguments', function() {
|
||||
var doc = {
|
||||
id: 'angular2/angular2.ngFor',
|
||||
name: 'ngFor',
|
||||
docType: 'class',
|
||||
decorators: [
|
||||
{
|
||||
name: 'Directive',
|
||||
arguments: ['{selector: \'[ng-for][ng-for-of]\', properties: [\'ngForOf\']}'],
|
||||
argumentInfo: [
|
||||
{ selector: '[ng-for][ng-for-of]', properties: ['ngForOf'] }
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var docs = processor.$process([doc]);
|
||||
|
||||
expect(doc).toEqual(jasmine.objectContaining({
|
||||
id: 'angular2/angular2.ngFor',
|
||||
name: 'ngFor',
|
||||
docType: 'directive',
|
||||
decorators: [
|
||||
{
|
||||
name: 'Directive',
|
||||
arguments: ['{selector: \'[ng-for][ng-for-of]\', properties: [\'ngForOf\']}'],
|
||||
argumentInfo: [
|
||||
{ selector: '[ng-for][ng-for-of]', properties: ['ngForOf'] }
|
||||
]
|
||||
}
|
||||
]
|
||||
}));
|
||||
|
||||
expect(doc.directiveOptions).toEqual({
|
||||
selector: '[ng-for][ng-for-of]',
|
||||
properties: ['ngForOf']
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,65 @@
|
|||
var _ = require('lodash');
|
||||
|
||||
/**
|
||||
* @dgProcessor
|
||||
* @description
|
||||
*
|
||||
*/
|
||||
module.exports = function matchUpDirectiveDecoratorsProcessor(aliasMap) {
|
||||
|
||||
return {
|
||||
$runAfter: ['ids-computed', 'paths-computed'],
|
||||
$runBefore: ['rendering-docs'],
|
||||
decoratorMappings: {
|
||||
'Inputs' : 'inputs',
|
||||
'Outputs' : 'outputs'
|
||||
},
|
||||
$process: function(docs) {
|
||||
var decoratorMappings = this.decoratorMappings;
|
||||
_.forEach(docs, function(doc) {
|
||||
if (doc.docType === 'directive') {
|
||||
doc.selector = doc.directiveOptions.selector;
|
||||
|
||||
for(decoratorName in decoratorMappings) {
|
||||
var propertyName = decoratorMappings[decoratorName];
|
||||
doc[propertyName] = getDecoratorValues(doc.directiveOptions[propertyName], decoratorName, doc.members);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
function getDecoratorValues(classDecoratorValues, memberDecoratorName, members) {
|
||||
var optionMap = {};
|
||||
var decoratorValues = {};
|
||||
|
||||
// Parse the class decorator
|
||||
_.forEach(classDecoratorValues, function(option) {
|
||||
// Options are of the form: "propName : bindingName" (bindingName is optional)
|
||||
var optionPair = option.split(':');
|
||||
var propertyName = optionPair.shift().trim();
|
||||
var bindingName = (optionPair.shift() || '').trim() || propertyName;
|
||||
|
||||
decoratorValues[propertyName] = {
|
||||
propertyName: propertyName,
|
||||
bindingName: bindingName
|
||||
};
|
||||
});
|
||||
|
||||
_.forEach(members, function(member) {
|
||||
_.forEach(member.decorators, function(decorator) {
|
||||
if (decorator.name === memberDecoratorName) {
|
||||
decoratorValues[member.name] = {
|
||||
propertyName: member.name,
|
||||
bindingName: decorator.arguments[0] || member.name
|
||||
};
|
||||
}
|
||||
});
|
||||
if (decoratorValues[member.name]) {
|
||||
decoratorValues[member.name].memberDoc = member;
|
||||
}
|
||||
});
|
||||
|
||||
return decoratorValues;
|
||||
}
|
|
@ -19,7 +19,10 @@ p.location-badge.
|
|||
*Not Yet Documented*
|
||||
{% else %}
|
||||
{$ doc.description | indentForMarkdown(2) | trimBlankLines $}
|
||||
{% endif -%}
|
||||
{% endif %}
|
||||
|
||||
{% block additional %}
|
||||
{% endblock %}
|
||||
|
||||
{%- if doc.decorators.length %}
|
||||
.l-main-section
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
{% include "lib/githubLinks.html" -%}
|
||||
{% include "lib/paramList.html" -%}
|
||||
{% extends 'class.template.html' -%}
|
||||
|
||||
{% block additional %}
|
||||
.l-main-section
|
||||
h2 Selector
|
||||
.l-sub-section
|
||||
h3.selector
|
||||
code {$ doc.directiveOptions.selector $}
|
||||
|
||||
.l-main-section
|
||||
h2 Inputs
|
||||
.l-sub-section
|
||||
h3.input {% for binding, property in doc.inputs %}
|
||||
code {$ property.bindingName | dashCase $}
|
||||
| bound to
|
||||
code {$ property.memberDoc.classDoc.name $}.{$ property.propertyName $}
|
||||
:markdown
|
||||
{$ property.memberDoc.description | indentForMarkdown(2) | trimBlankLines $}
|
||||
{% endfor %}
|
||||
|
||||
.l-main-section
|
||||
h2 Outputs
|
||||
.l-sub-section
|
||||
h3.input {% for binding, property in doc.outputs %}
|
||||
code {$ property.bindingName | dashCase $}
|
||||
| bound to
|
||||
code {$ property.memberDoc.classDoc.name $}.{$ property.propertyName $}
|
||||
:markdown
|
||||
{$ event.memberDoc.description | indentForMarkdown(2) | trimBlankLines $}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
|
@ -15,6 +15,7 @@ module.exports = new Package('angular-v2-docs', [jsdocPackage, nunjucksPackage,
|
|||
|
||||
// Register the processors
|
||||
.processor(require('./processors/convertPrivateClassesToInterfaces'))
|
||||
.processor(require('./processors/extractDirectiveClasses'))
|
||||
.processor(require('./processors/generateNavigationDoc'))
|
||||
.processor(require('./processors/extractTitleFromGuides'))
|
||||
.processor(require('./processors/createOverviewDump'))
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
var _ = require('lodash');
|
||||
var vm = require('vm');
|
||||
|
||||
module.exports = function extractDirectiveClassesProcessor() {
|
||||
return {
|
||||
$runAfter: ['processing-docs'],
|
||||
$runBefore: ['docs-processed'],
|
||||
decoratorTypes: ['Directive', 'Component', 'View'],
|
||||
$process: function(docs) {
|
||||
var decoratorTypes = this.decoratorTypes;
|
||||
|
||||
_.forEach(docs, function(doc) {
|
||||
|
||||
_.forEach(doc.decorators, function(decorator) {
|
||||
|
||||
if (decoratorTypes.indexOf(decorator.name) !== -1) {
|
||||
|
||||
// We use this sneaky vm trick to extract the object literal
|
||||
// argument from the decorator's constructor call
|
||||
var args = decorator.arguments ?
|
||||
vm.runInNewContext('dummy = ' + decorator.arguments[0]) : {};
|
||||
|
||||
doc[decorator.name.toLowerCase() + 'Options'] = args;
|
||||
doc.docType = 'directive';
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return docs;
|
||||
}
|
||||
};
|
||||
};
|
|
@ -0,0 +1,45 @@
|
|||
var mockPackage = require('../mocks/mockPackage');
|
||||
var Dgeni = require('dgeni');
|
||||
|
||||
describe('extractDirectiveClasses processor', function() {
|
||||
var dgeni, injector, processor;
|
||||
|
||||
beforeEach(function() {
|
||||
dgeni = new Dgeni([mockPackage()]);
|
||||
injector = dgeni.configureInjector();
|
||||
processor = injector.get('extractDirectiveClassesProcessor');
|
||||
});
|
||||
|
||||
it('should extract specified decorator arguments', function() {
|
||||
var doc = {
|
||||
id: 'angular2/angular2.ngFor',
|
||||
name: 'ngFor',
|
||||
docType: 'class',
|
||||
decorators: [
|
||||
{
|
||||
name: 'Directive',
|
||||
arguments: ['{selector: \'[ng-for][ng-for-of]\', properties: [\'ngForOf\']}']
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var docs = processor.$process([doc]);
|
||||
|
||||
expect(doc).toEqual(jasmine.objectContaining({
|
||||
id: 'angular2/angular2.ngFor',
|
||||
name: 'ngFor',
|
||||
docType: 'directive',
|
||||
decorators: [
|
||||
{
|
||||
name: 'Directive',
|
||||
arguments: ['{selector: \'[ng-for][ng-for-of]\', properties: [\'ngForOf\']}']
|
||||
}
|
||||
]
|
||||
}));
|
||||
|
||||
expect(doc.directiveOptions).toEqual({
|
||||
selector: '[ng-for][ng-for-of]',
|
||||
properties: ['ngForOf']
|
||||
});
|
||||
});
|
||||
});
|
|
@ -44,12 +44,14 @@ module.exports = new Package('typescript-parsing', [basePackage])
|
|||
computeIdsProcessor.idTemplates.push({
|
||||
docTypes: ['member'],
|
||||
idTemplate: '${classDoc.id}.${name}',
|
||||
getAliases: function(doc) { return [doc.id]; }
|
||||
getAliases: function(doc) {
|
||||
return doc.classDoc.aliases.map(function(alias) { return alias + '.' + doc.name; });
|
||||
}
|
||||
});
|
||||
|
||||
computePathsProcessor.pathTemplates.push({
|
||||
docTypes: ['member'],
|
||||
pathTemplate: '${classDoc.path}/${name}',
|
||||
pathTemplate: '${classDoc.path}#${name}',
|
||||
getOutputPath: function() {} // These docs are not written to their own file, instead they are part of their class doc
|
||||
});
|
||||
|
||||
|
|
|
@ -301,6 +301,7 @@ module.exports = function readTypeScriptModules(tsParser, modules, getFileInfo,
|
|||
|
||||
|
||||
function getDecorators(symbol) {
|
||||
|
||||
var declaration = symbol.valueDeclaration || symbol.declarations[0];
|
||||
var sourceFile = ts.getSourceFileOfNode(declaration);
|
||||
|
||||
|
@ -310,12 +311,33 @@ module.exports = function readTypeScriptModules(tsParser, modules, getFileInfo,
|
|||
name: decorator.expression ? decorator.expression.text : decorator.text,
|
||||
arguments: decorator.arguments && decorator.arguments.map(function(argument) {
|
||||
return getText(sourceFile, argument).trim();
|
||||
})
|
||||
}),
|
||||
argumentInfo: decorator.arguments && decorator.arguments.map(function(argument) {
|
||||
return parseArgument(argument);
|
||||
}),
|
||||
expression: decorator
|
||||
};
|
||||
});
|
||||
return decorators;
|
||||
}
|
||||
|
||||
function parseProperties(properties) {
|
||||
var result = {};
|
||||
_.forEach(properties, function(property) {
|
||||
result[property.name.text] = parseArgument(property.initializer);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseArgument(argument) {
|
||||
if (argument.text) return argument.text;
|
||||
if (argument.properties) return parseProperties(argument.properties);
|
||||
if (argument.elements) return argument.elements.map(function(element) { return element.text; });
|
||||
var sourceFile = ts.getSourceFileOfNode(argument);
|
||||
var text = getText(sourceFile, argument).trim();
|
||||
return text;
|
||||
}
|
||||
|
||||
function getParameters(typeChecker, symbol) {
|
||||
var declaration = symbol.valueDeclaration || symbol.declarations[0];
|
||||
var sourceFile = ts.getSourceFileOfNode(declaration);
|
||||
|
|
Loading…
Reference in New Issue