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'))
|
.factory(require('./services/renderMarkdown'))
|
||||||
.processor(require('./processors/addJadeDataDocsProcessor'))
|
.processor(require('./processors/addJadeDataDocsProcessor'))
|
||||||
.processor(require('./processors/filterUnwantedDecorators'))
|
.processor(require('./processors/filterUnwantedDecorators'))
|
||||||
|
.processor(require('./processors/extractDirectiveClasses'))
|
||||||
|
.processor(require('./processors/matchUpDirectiveDecorators'))
|
||||||
|
|
||||||
// overrides base packageInfo and returns the one for the 'angular/angular' repo.
|
// overrides base packageInfo and returns the one for the 'angular/angular' repo.
|
||||||
.factory(require('./services/packageInfo'))
|
.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*
|
*Not Yet Documented*
|
||||||
{% else %}
|
{% else %}
|
||||||
{$ doc.description | indentForMarkdown(2) | trimBlankLines $}
|
{$ doc.description | indentForMarkdown(2) | trimBlankLines $}
|
||||||
{% endif -%}
|
{% endif %}
|
||||||
|
|
||||||
|
{% block additional %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{%- if doc.decorators.length %}
|
{%- if doc.decorators.length %}
|
||||||
.l-main-section
|
.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
|
// Register the processors
|
||||||
.processor(require('./processors/convertPrivateClassesToInterfaces'))
|
.processor(require('./processors/convertPrivateClassesToInterfaces'))
|
||||||
|
.processor(require('./processors/extractDirectiveClasses'))
|
||||||
.processor(require('./processors/generateNavigationDoc'))
|
.processor(require('./processors/generateNavigationDoc'))
|
||||||
.processor(require('./processors/extractTitleFromGuides'))
|
.processor(require('./processors/extractTitleFromGuides'))
|
||||||
.processor(require('./processors/createOverviewDump'))
|
.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({
|
computeIdsProcessor.idTemplates.push({
|
||||||
docTypes: ['member'],
|
docTypes: ['member'],
|
||||||
idTemplate: '${classDoc.id}.${name}',
|
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({
|
computePathsProcessor.pathTemplates.push({
|
||||||
docTypes: ['member'],
|
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
|
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) {
|
function getDecorators(symbol) {
|
||||||
|
|
||||||
var declaration = symbol.valueDeclaration || symbol.declarations[0];
|
var declaration = symbol.valueDeclaration || symbol.declarations[0];
|
||||||
var sourceFile = ts.getSourceFileOfNode(declaration);
|
var sourceFile = ts.getSourceFileOfNode(declaration);
|
||||||
|
|
||||||
@ -310,12 +311,33 @@ module.exports = function readTypeScriptModules(tsParser, modules, getFileInfo,
|
|||||||
name: decorator.expression ? decorator.expression.text : decorator.text,
|
name: decorator.expression ? decorator.expression.text : decorator.text,
|
||||||
arguments: decorator.arguments && decorator.arguments.map(function(argument) {
|
arguments: decorator.arguments && decorator.arguments.map(function(argument) {
|
||||||
return getText(sourceFile, argument).trim();
|
return getText(sourceFile, argument).trim();
|
||||||
})
|
}),
|
||||||
|
argumentInfo: decorator.arguments && decorator.arguments.map(function(argument) {
|
||||||
|
return parseArgument(argument);
|
||||||
|
}),
|
||||||
|
expression: decorator
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
return decorators;
|
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) {
|
function getParameters(typeChecker, symbol) {
|
||||||
var declaration = symbol.valueDeclaration || symbol.declarations[0];
|
var declaration = symbol.valueDeclaration || symbol.declarations[0];
|
||||||
var sourceFile = ts.getSourceFileOfNode(declaration);
|
var sourceFile = ts.getSourceFileOfNode(declaration);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user