build(aio): refactor dgeni packages
This is to tidy up the `author-packagse`, which currently duplicates a lot of the configuration in the main packages. We need to DRY this up so that we don't fall foul of a change in one being missed in the other.
This commit is contained in:

committed by
Pete Bacon Darwin

parent
7a8bd99ab1
commit
3cad5da5a4
37
aio/tools/transforms/angular-api-package/processors/addNotYetDocumentedProperty.js
vendored
Normal file
37
aio/tools/transforms/angular-api-package/processors/addNotYetDocumentedProperty.js
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
module.exports = function addNotYetDocumentedProperty(EXPORT_DOC_TYPES, log, createDocMessage) {
|
||||
return {
|
||||
$runAfter: ['tags-parsed'],
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: function(docs) {
|
||||
docs.forEach(function(doc) {
|
||||
|
||||
if (EXPORT_DOC_TYPES.indexOf(doc.docType) === -1) return;
|
||||
|
||||
// NotYetDocumented means that no top level comments and no member level comments
|
||||
doc.notYetDocumented = notYetDocumented(doc);
|
||||
|
||||
if (doc.constructorDoc) {
|
||||
doc.constructorDoc.notYetDocumented = notYetDocumented(doc.constructorDoc);
|
||||
doc.notYetDocumented = doc.notYetDocumented && doc.constructorDoc.notYetDocumented;
|
||||
}
|
||||
|
||||
if (doc.members) {
|
||||
doc.members.forEach(function(member) {
|
||||
member.notYetDocumented = notYetDocumented(member);
|
||||
doc.notYetDocumented = doc.notYetDocumented && member.notYetDocumented;
|
||||
});
|
||||
}
|
||||
|
||||
if (doc.notYetDocumented) {
|
||||
log.debug(createDocMessage('Not yet documented', doc));
|
||||
}
|
||||
});
|
||||
|
||||
return docs;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
function notYetDocumented(doc) {
|
||||
return !doc.noDescription && doc.description.trim().length == 0;
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
var testPackage = require('../../helpers/test-package');
|
||||
var Dgeni = require('dgeni');
|
||||
|
||||
describe('addNotYetDocumentedProperty', function() {
|
||||
var dgeni, injector, processor;
|
||||
|
||||
beforeEach(function() {
|
||||
dgeni = new Dgeni([testPackage('angular-api-package')]);
|
||||
injector = dgeni.configureInjector();
|
||||
processor = injector.get('addNotYetDocumentedProperty');
|
||||
});
|
||||
|
||||
it('should mark export docs with no description as "not yet documented"', function() {
|
||||
var a, b, c, d, a1, b1, c1, d1;
|
||||
var docs = [
|
||||
a = {id: 'a', docType: 'interface', description: 'some content'},
|
||||
b = {id: 'b', docType: 'class', description: 'some content'},
|
||||
c = {id: 'c', docType: 'var', description: 'some content'},
|
||||
d = {id: 'd', docType: 'function', description: 'some content'},
|
||||
a1 = {id: 'a1', docType: 'interface', description: ''},
|
||||
b1 = {id: 'b1', docType: 'class', description: ''},
|
||||
c1 = {id: 'c1', docType: 'var', description: ''},
|
||||
d1 = {id: 'd1', docType: 'function', description: ''}
|
||||
];
|
||||
|
||||
processor.$process(docs);
|
||||
|
||||
expect(a.notYetDocumented).toBeFalsy();
|
||||
expect(b.notYetDocumented).toBeFalsy();
|
||||
expect(c.notYetDocumented).toBeFalsy();
|
||||
expect(d.notYetDocumented).toBeFalsy();
|
||||
|
||||
expect(a1.notYetDocumented).toBeTruthy();
|
||||
expect(b1.notYetDocumented).toBeTruthy();
|
||||
expect(c1.notYetDocumented).toBeTruthy();
|
||||
expect(d1.notYetDocumented).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should mark member docs with no description as "not yet documented"', function() {
|
||||
var a, a1, a2, b, b1, b2, c, c1, c2;
|
||||
var docs = [
|
||||
a = {
|
||||
id: 'a',
|
||||
docType: 'interface',
|
||||
description: 'some content',
|
||||
members: [a1 = {id: 'a1', description: 'some content'}, a2 = {id: 'a2', description: ''}]
|
||||
},
|
||||
b = {
|
||||
id: 'b',
|
||||
docType: 'class',
|
||||
description: '',
|
||||
members: [b1 = {id: 'b1', description: 'some content'}, b2 = {id: 'b2', description: ''}]
|
||||
},
|
||||
c = {
|
||||
id: 'c',
|
||||
docType: 'class',
|
||||
description: '',
|
||||
members: [c1 = {id: 'c1', description: ''}, c2 = {id: 'c2', description: ''}]
|
||||
},
|
||||
];
|
||||
|
||||
processor.$process(docs);
|
||||
|
||||
expect(a.notYetDocumented).toBeFalsy();
|
||||
expect(b.notYetDocumented).toBeFalsy();
|
||||
expect(c.notYetDocumented).toBeTruthy();
|
||||
|
||||
expect(a1.notYetDocumented).toBeFalsy();
|
||||
expect(a2.notYetDocumented).toBeTruthy();
|
||||
expect(b1.notYetDocumented).toBeFalsy();
|
||||
expect(b2.notYetDocumented).toBeTruthy();
|
||||
expect(c1.notYetDocumented).toBeTruthy();
|
||||
expect(c2.notYetDocumented).toBeTruthy();
|
||||
});
|
||||
|
||||
|
||||
it('should mark constructor doc with no description as "not yet documented"', function() {
|
||||
var a, a1, b, b1;
|
||||
var docs = [
|
||||
a = {
|
||||
id: 'a',
|
||||
docType: 'interface',
|
||||
description: '',
|
||||
constructorDoc: a1 = {id: 'a1', description: 'some content'}
|
||||
},
|
||||
b = {
|
||||
id: 'b',
|
||||
docType: 'interface',
|
||||
description: '',
|
||||
constructorDoc: b1 = {id: 'b1', description: ''}
|
||||
}
|
||||
];
|
||||
|
||||
processor.$process(docs);
|
||||
|
||||
expect(a.notYetDocumented).toBeFalsy();
|
||||
expect(b.notYetDocumented).toBeTruthy();
|
||||
|
||||
expect(a1.notYetDocumented).toBeFalsy();
|
||||
expect(b1.notYetDocumented).toBeTruthy();
|
||||
});
|
||||
|
||||
|
||||
it('should not mark documents explicity tagged as `@noDescription`', function() {
|
||||
var a, a1, a2, b, b1, b2, c, c1, c2;
|
||||
var docs = [
|
||||
a = {
|
||||
id: 'a',
|
||||
docType: 'interface',
|
||||
description: 'some content',
|
||||
members: [
|
||||
a1 = {id: 'a1', description: 'some content'},
|
||||
a2 = {id: 'a2', description: '', noDescription: true}
|
||||
]
|
||||
},
|
||||
b = {
|
||||
id: 'b',
|
||||
docType: 'class',
|
||||
description: '',
|
||||
members: [
|
||||
b1 = {id: 'b1', description: 'some content'},
|
||||
b2 = {id: 'b2', description: '', noDescription: true}
|
||||
]
|
||||
},
|
||||
c = {
|
||||
id: 'c',
|
||||
docType: 'class',
|
||||
description: '',
|
||||
noDescription: true,
|
||||
members: [c1 = {id: 'c1', description: ''}, c2 = {id: 'c2', description: ''}]
|
||||
},
|
||||
];
|
||||
|
||||
processor.$process(docs);
|
||||
|
||||
expect(a.notYetDocumented).toBeFalsy();
|
||||
expect(b.notYetDocumented).toBeFalsy();
|
||||
expect(c.notYetDocumented).toBeFalsy();
|
||||
|
||||
expect(a1.notYetDocumented).toBeFalsy();
|
||||
expect(a2.notYetDocumented).toBeFalsy();
|
||||
expect(b1.notYetDocumented).toBeFalsy();
|
||||
expect(b2.notYetDocumented).toBeFalsy();
|
||||
expect(c1.notYetDocumented).toBeTruthy();
|
||||
expect(c2.notYetDocumented).toBeTruthy();
|
||||
});
|
||||
});
|
11
aio/tools/transforms/angular-api-package/processors/convertPrivateClassesToInterfaces.js
vendored
Normal file
11
aio/tools/transforms/angular-api-package/processors/convertPrivateClassesToInterfaces.js
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
module.exports = function convertPrivateClassesToInterfacesProcessor(
|
||||
convertPrivateClassesToInterfaces) {
|
||||
return {
|
||||
$runAfter: ['processing-docs'],
|
||||
$runBefore: ['docs-processed'],
|
||||
$process: function(docs) {
|
||||
convertPrivateClassesToInterfaces(docs, false);
|
||||
return docs;
|
||||
}
|
||||
};
|
||||
};
|
29
aio/tools/transforms/angular-api-package/processors/extractDecoratedClasses.js
vendored
Normal file
29
aio/tools/transforms/angular-api-package/processors/extractDecoratedClasses.js
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
var _ = require('lodash');
|
||||
|
||||
module.exports = function extractDecoratedClassesProcessor(EXPORT_DOC_TYPES) {
|
||||
|
||||
// Add the "directive" docType into those that can be exported from a module
|
||||
EXPORT_DOC_TYPES.push('directive', 'pipe');
|
||||
|
||||
return {
|
||||
$runAfter: ['processing-docs'],
|
||||
$runBefore: ['docs-processed'],
|
||||
decoratorTypes: ['Directive', 'Component', 'Pipe'],
|
||||
$process: function(docs) {
|
||||
var decoratorTypes = this.decoratorTypes;
|
||||
|
||||
_.forEach(docs, function(doc) {
|
||||
|
||||
_.forEach(doc.decorators, function(decorator) {
|
||||
|
||||
if (decoratorTypes.indexOf(decorator.name) !== -1) {
|
||||
doc.docType = decorator.name.toLowerCase();
|
||||
doc[doc.docType + 'Options'] = decorator.argumentInfo[0];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return docs;
|
||||
}
|
||||
};
|
||||
};
|
@ -0,0 +1,48 @@
|
||||
var testPackage = require('../../helpers/test-package');
|
||||
var Dgeni = require('dgeni');
|
||||
|
||||
describe('extractDecoratedClasses processor', function() {
|
||||
var dgeni, injector, processor;
|
||||
|
||||
beforeEach(function() {
|
||||
dgeni = new Dgeni([testPackage('angular-api-package')]);
|
||||
injector = dgeni.configureInjector();
|
||||
processor = injector.get('extractDecoratedClassesProcessor');
|
||||
});
|
||||
|
||||
it('should extract specified decorator arguments', function() {
|
||||
var doc1 = {
|
||||
id: '@angular/common/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 doc2 = {
|
||||
id: '@angular/core/DecimalPipe',
|
||||
name: 'DecimalPipe',
|
||||
docType: 'class',
|
||||
decorators:
|
||||
[{name: 'Pipe', arguments: ['{name: \'number\'}'], argumentInfo: [{name: 'number'}]}]
|
||||
};
|
||||
|
||||
processor.$process([doc1, doc2]);
|
||||
|
||||
expect(doc1).toEqual(jasmine.objectContaining({
|
||||
id: '@angular/common/ngFor',
|
||||
name: 'ngFor',
|
||||
docType: 'directive',
|
||||
directiveOptions: {selector: '[ng-for][ng-for-of]', properties: ['ngForOf']}
|
||||
}));
|
||||
|
||||
expect(doc2).toEqual(jasmine.objectContaining({
|
||||
id: '@angular/core/DecimalPipe',
|
||||
name: 'DecimalPipe',
|
||||
docType: 'pipe',
|
||||
pipeOptions: {name: 'number'}
|
||||
}));
|
||||
});
|
||||
});
|
13
aio/tools/transforms/angular-api-package/processors/filterIgnoredDocs.js
vendored
Normal file
13
aio/tools/transforms/angular-api-package/processors/filterIgnoredDocs.js
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Filter out docs whose id matches a pattern in the `filterIgnoredDocs.ignore` list
|
||||
*/
|
||||
module.exports = function filterIgnoredDocs() {
|
||||
return {
|
||||
ignore: [],
|
||||
$runAfter: ['ids-computed'],
|
||||
$runBefore: ['computing-paths'],
|
||||
$process: function(docs) {
|
||||
return docs.filter(doc => !this.ignore.some(regexp => regexp.test(doc.id)));
|
||||
}
|
||||
};
|
||||
};
|
@ -0,0 +1,39 @@
|
||||
const testPackage = require('../../helpers/test-package');
|
||||
const processorFactory = require('./filterIgnoredDocs');
|
||||
const Dgeni = require('dgeni');
|
||||
|
||||
describe('filterIgnoredDocs processor', () => {
|
||||
|
||||
it('should be available on the injector', () => {
|
||||
const dgeni = new Dgeni([testPackage('angular-api-package')]);
|
||||
const injector = dgeni.configureInjector();
|
||||
const processor = injector.get('filterIgnoredDocs');
|
||||
expect(processor.$process).toBeDefined();
|
||||
});
|
||||
|
||||
it('should run before the correct processor', () => {
|
||||
const processor = processorFactory();
|
||||
expect(processor.$runBefore).toEqual(['computing-paths']);
|
||||
});
|
||||
|
||||
it('should run after the correct processor', () => {
|
||||
const processor = processorFactory();
|
||||
expect(processor.$runAfter).toEqual(['ids-computed']);
|
||||
});
|
||||
|
||||
it('should remove docs that match the ignore list', () => {
|
||||
const processor = processorFactory();
|
||||
processor.ignore = [/\/VERSION$/, /ignore-me/];
|
||||
const docs = [
|
||||
{ id: 'public1'},
|
||||
{ id: 'ignore-me/something' },
|
||||
{ id: 'public2'},
|
||||
{ id: 'and-me/VERSION' }
|
||||
];
|
||||
const filteredDocs = processor.$process(docs);
|
||||
expect(filteredDocs).toEqual([
|
||||
{ id: 'public1'},
|
||||
{ id: 'public2'}
|
||||
]);
|
||||
});
|
||||
});
|
7
aio/tools/transforms/angular-api-package/processors/filterMemberDocs.js
vendored
Normal file
7
aio/tools/transforms/angular-api-package/processors/filterMemberDocs.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
module.exports = function filterMemberDocs() {
|
||||
return {
|
||||
$runAfter: ['extra-docs-added'], $runBefore: ['computing-paths'], $process: function(docs) {
|
||||
return docs.filter(function(doc) { return doc.docType !== 'member'; });
|
||||
}
|
||||
};
|
||||
};
|
9
aio/tools/transforms/angular-api-package/processors/filterPrivateDocs.js
vendored
Normal file
9
aio/tools/transforms/angular-api-package/processors/filterPrivateDocs.js
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
module.exports = function filterPrivateDocs() {
|
||||
return {
|
||||
$runAfter: ['extra-docs-added'],
|
||||
$runBefore: ['computing-paths'],
|
||||
$process: function(docs) {
|
||||
return docs.filter(function(doc) { return doc.privateExport !== true; });
|
||||
}
|
||||
};
|
||||
};
|
@ -0,0 +1,40 @@
|
||||
const testPackage = require('../../helpers/test-package');
|
||||
const processorFactory = require('./filterPrivateDocs');
|
||||
const Dgeni = require('dgeni');
|
||||
|
||||
describe('filterPrivateDocs processor', () => {
|
||||
|
||||
it('should be available on the injector', () => {
|
||||
const dgeni = new Dgeni([testPackage('angular-api-package')]);
|
||||
const injector = dgeni.configureInjector();
|
||||
const processor = injector.get('filterPrivateDocs');
|
||||
expect(processor.$process).toBeDefined();
|
||||
});
|
||||
|
||||
it('should run before the correct processor', () => {
|
||||
const processor = processorFactory();
|
||||
expect(processor.$runBefore).toEqual(['computing-paths']);
|
||||
});
|
||||
|
||||
it('should run after the correct processor', () => {
|
||||
const processor = processorFactory();
|
||||
expect(processor.$runAfter).toEqual(['extra-docs-added']);
|
||||
});
|
||||
|
||||
it('should remove docs that are marked as private exports', () => {
|
||||
const processor = processorFactory();
|
||||
const docs = [
|
||||
{ name: 'public1'},
|
||||
{ name: 'ɵPrivate1', privateExport: true },
|
||||
{ name: 'public2'},
|
||||
{ name: 'ɵPrivate2', privateExport: true },
|
||||
{ id: 'other'}
|
||||
];
|
||||
const filteredDocs = processor.$process(docs);
|
||||
expect(filteredDocs).toEqual([
|
||||
{ name: 'public1'},
|
||||
{ name: 'public2'},
|
||||
{ id: 'other'}
|
||||
]);
|
||||
});
|
||||
});
|
55
aio/tools/transforms/angular-api-package/processors/generateApiListDoc.js
vendored
Normal file
55
aio/tools/transforms/angular-api-package/processors/generateApiListDoc.js
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
module.exports = function generateApiListDoc() {
|
||||
|
||||
return {
|
||||
$runAfter: ['extra-docs-added'],
|
||||
$runBefore: ['rendering-docs'],
|
||||
outputFolder: null,
|
||||
$validate: {outputFolder: {presence: true}},
|
||||
$process: function(docs) {
|
||||
docs.push({
|
||||
docType: 'api-list-data',
|
||||
template: 'json-doc.template.json',
|
||||
path: this.outputFolder + '/api-list.json',
|
||||
outputPath: this.outputFolder + '/api-list.json',
|
||||
data: docs
|
||||
.filter(doc => doc.docType === 'module')
|
||||
.map(getModuleInfo)
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
function getModuleInfo(moduleDoc) {
|
||||
const moduleName = moduleDoc.id.replace(/\/index$/, '');
|
||||
return {
|
||||
name: moduleName.toLowerCase(),
|
||||
title: moduleName,
|
||||
items: moduleDoc.exports
|
||||
// Ignore internals and private exports (indicated by the ɵ prefix)
|
||||
.filter(doc => !doc.internal && !doc.privateExport).map(getExportInfo)
|
||||
};
|
||||
}
|
||||
|
||||
function getExportInfo(exportDoc) {
|
||||
return {
|
||||
name: exportDoc.name.toLowerCase(),
|
||||
title: exportDoc.name,
|
||||
path: exportDoc.path,
|
||||
docType: getDocType(exportDoc),
|
||||
stability: getStability(exportDoc),
|
||||
securityRisk: !!exportDoc.security
|
||||
};
|
||||
}
|
||||
|
||||
function getDocType(doc) {
|
||||
// We map `let` and `var` types to `const`
|
||||
if (['let', 'var'].indexOf(doc.docType) !== -1) {
|
||||
return 'const';
|
||||
}
|
||||
return doc.docType;
|
||||
}
|
||||
|
||||
const stabilityProperties = ['stable', 'experimental', 'deprecated'];
|
||||
function getStability(doc) {
|
||||
return stabilityProperties.find(prop => doc.hasOwnProperty(prop)) || '';
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
const testPackage = require('../../helpers/test-package');
|
||||
const processorFactory = require('./generateApiListDoc');
|
||||
const Dgeni = require('dgeni');
|
||||
|
||||
describe('generateApiListDoc processor', () => {
|
||||
|
||||
it('should be available on the injector', () => {
|
||||
const dgeni = new Dgeni([testPackage('angular-api-package')]);
|
||||
const injector = dgeni.configureInjector();
|
||||
const processor = injector.get('generateApiListDoc');
|
||||
expect(processor.$process).toBeDefined();
|
||||
});
|
||||
|
||||
it('should run after the correct processor', () => {
|
||||
const processor = processorFactory();
|
||||
expect(processor.$runAfter).toEqual(['extra-docs-added']);
|
||||
});
|
||||
|
||||
it('should run before the correct processor', () => {
|
||||
const processor = processorFactory();
|
||||
expect(processor.$runBefore).toEqual(['rendering-docs']);
|
||||
});
|
||||
|
||||
it('should create a new api list doc', () => {
|
||||
const processor = processorFactory();
|
||||
const docs = [];
|
||||
processor.outputFolder = 'test/path';
|
||||
processor.$process(docs);
|
||||
expect(docs[0]).toEqual({
|
||||
docType: 'api-list-data',
|
||||
template: 'json-doc.template.json',
|
||||
path: 'test/path/api-list.json',
|
||||
outputPath: 'test/path/api-list.json',
|
||||
data: []
|
||||
});
|
||||
});
|
||||
|
||||
it('should add an info object to the doc for each module doc', () => {
|
||||
const processor = processorFactory();
|
||||
const docs = [
|
||||
{ docType: 'module', id: '@angular/common/index', exports: [] },
|
||||
{ docType: 'module', id: '@angular/core/index', exports: [] },
|
||||
{ docType: 'module', id: '@angular/http/index', exports: [] },
|
||||
];
|
||||
processor.$process(docs);
|
||||
expect(docs[3].data).toEqual([
|
||||
{ name: '@angular/common', title: '@angular/common', items: [] },
|
||||
{ name: '@angular/core', title: '@angular/core', items: [] },
|
||||
{ name: '@angular/http', title: '@angular/http', items: [] },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should add info about each export on each module', () => {
|
||||
const processor = processorFactory();
|
||||
const docs = [
|
||||
{ docType: 'module', id: '@angular/common/index', exports: [
|
||||
{ docType: 'directive', name: 'AaaAaa', path: 'aaa' },
|
||||
{ docType: 'pipe', name: 'BbbBbb', path: 'bbb' },
|
||||
{ docType: 'decorator', name: 'CccCcc', path: 'ccc' },
|
||||
{ docType: 'class', name: 'DddDdd', path: 'ddd' }
|
||||
] },
|
||||
{ docType: 'module', id: '@angular/core/index', exports: [
|
||||
{ docType: 'interface', name: 'EeeEee', path: 'eee' },
|
||||
{ docType: 'function', name: 'FffFff', path: 'fff' },
|
||||
{ docType: 'enum', name: 'GggGgg', path: 'ggg' },
|
||||
{ docType: 'type-alias', name: 'HhhHhh', path: 'hhh' },
|
||||
{ docType: 'const', name: 'IiiIii', path: 'iii' },
|
||||
] },
|
||||
];
|
||||
processor.$process(docs);
|
||||
expect(docs[2].data[0].items).toEqual([
|
||||
{ docType: 'directive', title: 'AaaAaa', name: 'aaaaaa', path: 'aaa', stability: '', securityRisk: false },
|
||||
{ docType: 'pipe', title: 'BbbBbb', name: 'bbbbbb', path: 'bbb', stability: '', securityRisk: false },
|
||||
{ docType: 'decorator', title: 'CccCcc', name: 'cccccc', path: 'ccc', stability: '', securityRisk: false },
|
||||
{ docType: 'class', title: 'DddDdd', name: 'dddddd', path: 'ddd', stability: '', securityRisk: false }
|
||||
]);
|
||||
expect(docs[2].data[1].items).toEqual([
|
||||
{ docType: 'interface', title: 'EeeEee', name: 'eeeeee', path: 'eee', stability: '', securityRisk: false },
|
||||
{ docType: 'function', title: 'FffFff', name: 'ffffff', path: 'fff', stability: '', securityRisk: false },
|
||||
{ docType: 'enum', title: 'GggGgg', name: 'gggggg', path: 'ggg', stability: '', securityRisk: false },
|
||||
{ docType: 'type-alias', title: 'HhhHhh', name: 'hhhhhh', path: 'hhh', stability: '', securityRisk: false },
|
||||
{ docType: 'const', title: 'IiiIii', name: 'iiiiii', path: 'iii', stability: '', securityRisk: false },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should ignore internal and private exports', () => {
|
||||
const processor = processorFactory();
|
||||
const docs = [
|
||||
{ docType: 'module', id: '@angular/common/index', exports: [
|
||||
{ docType: 'directive', name: 'AaaAaa', path: 'aaa', internal: true },
|
||||
{ docType: 'class', name: 'XxxXxx', path: 'xxx', privateExport: true },
|
||||
{ docType: 'pipe', name: 'BbbBbb', path: 'bbb' }
|
||||
]}
|
||||
];
|
||||
processor.$process(docs);
|
||||
expect(docs[1].data[0].items).toEqual([
|
||||
{ docType: 'pipe', title: 'BbbBbb', name: 'bbbbbb', path: 'bbb', stability: '', securityRisk: false },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should convert `let` and `var` docTypes to `const`', () => {
|
||||
const processor = processorFactory();
|
||||
const docs = [
|
||||
{ docType: 'module', id: '@angular/common/index', exports: [
|
||||
{ docType: 'var', name: 'AaaAaa', path: 'aaa' },
|
||||
{ docType: 'let', name: 'BbbBbb', path: 'bbb' },
|
||||
]}
|
||||
];
|
||||
processor.$process(docs);
|
||||
expect(docs[1].data[0].items).toEqual([
|
||||
{ docType: 'const', title: 'AaaAaa', name: 'aaaaaa', path: 'aaa', stability: '', securityRisk: false },
|
||||
{ docType: 'const', title: 'BbbBbb', name: 'bbbbbb', path: 'bbb', stability: '', securityRisk: false },
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
it('should convert security to a boolean securityRisk', () => {
|
||||
const processor = processorFactory();
|
||||
const docs = [
|
||||
{ docType: 'module', id: '@angular/common/index', exports: [
|
||||
{ docType: 'class', name: 'AaaAaa', path: 'aaa', security: 'This is a security risk' },
|
||||
{ docType: 'class', name: 'BbbBbb', path: 'bbb', security: '' },
|
||||
]}
|
||||
];
|
||||
processor.$process(docs);
|
||||
expect(docs[1].data[0].items).toEqual([
|
||||
{ docType: 'class', title: 'AaaAaa', name: 'aaaaaa', path: 'aaa', stability: '', securityRisk: true },
|
||||
{ docType: 'class', title: 'BbbBbb', name: 'bbbbbb', path: 'bbb', stability: '', securityRisk: false },
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
it('should convert stability tags to the stable string property', () => {
|
||||
const processor = processorFactory();
|
||||
const docs = [
|
||||
{ docType: 'module', id: '@angular/common/index', exports: [
|
||||
{ docType: 'class', name: 'AaaAaa', path: 'aaa', stable: undefined },
|
||||
{ docType: 'class', name: 'BbbBbb', path: 'bbb', experimental: 'Some message' },
|
||||
{ docType: 'class', name: 'CccCcc', path: 'ccc', deprecated: null },
|
||||
{ docType: 'class', name: 'DddDdd', path: 'ddd' },
|
||||
]}
|
||||
];
|
||||
processor.$process(docs);
|
||||
expect(docs[1].data[0].items).toEqual([
|
||||
{ docType: 'class', title: 'AaaAaa', name: 'aaaaaa', path: 'aaa', stability: 'stable', securityRisk: false },
|
||||
{ docType: 'class', title: 'BbbBbb', name: 'bbbbbb', path: 'bbb', stability: 'experimental', securityRisk: false },
|
||||
{ docType: 'class', title: 'CccCcc', name: 'cccccc', path: 'ccc', stability: 'deprecated', securityRisk: false },
|
||||
{ docType: 'class', title: 'DddDdd', name: 'dddddd', path: 'ddd', stability: '', securityRisk: false },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
13
aio/tools/transforms/angular-api-package/processors/markBarredODocsAsPrivate.js
vendored
Normal file
13
aio/tools/transforms/angular-api-package/processors/markBarredODocsAsPrivate.js
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
module.exports = function markBarredODocsAsPrivate() {
|
||||
return {
|
||||
$runAfter: ['readTypeScriptModules'],
|
||||
$runBefore: ['adding-extra-docs'],
|
||||
$process: function(docs) {
|
||||
docs.forEach(doc => {
|
||||
if (doc.name && doc.name.indexOf('ɵ') === 0) {
|
||||
doc.privateExport = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
@ -0,0 +1,28 @@
|
||||
const testPackage = require('../../helpers/test-package');
|
||||
const processorFactory = require('./markBarredODocsAsPrivate');
|
||||
const Dgeni = require('dgeni');
|
||||
|
||||
describe('generateApiListDoc processor', () => {
|
||||
|
||||
it('should be available on the injector', () => {
|
||||
const dgeni = new Dgeni([testPackage('angular-api-package')]);
|
||||
const injector = dgeni.configureInjector();
|
||||
const processor = injector.get('markBarredODocsAsPrivate');
|
||||
expect(processor.$process).toBeDefined();
|
||||
expect(processor.$runAfter).toContain('readTypeScriptModules');
|
||||
expect(processor.$runBefore).toContain('adding-extra-docs');
|
||||
});
|
||||
|
||||
it('should mark docs starting with barred-o ɵ as private', () => {
|
||||
const processor = processorFactory();
|
||||
const docs = [
|
||||
{ name: 'ɵPrivate' },
|
||||
{ name: 'public' }
|
||||
];
|
||||
processor.$process(docs);
|
||||
|
||||
expect(docs[0].privateExport).toBeTruthy();
|
||||
expect(docs[1].privateExport).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
61
aio/tools/transforms/angular-api-package/processors/matchUpDirectiveDecorators.js
vendored
Normal file
61
aio/tools/transforms/angular-api-package/processors/matchUpDirectiveDecorators.js
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
var _ = require('lodash');
|
||||
|
||||
/**
|
||||
* @dgProcessor
|
||||
* @description
|
||||
*
|
||||
*/
|
||||
module.exports = function matchUpDirectiveDecoratorsProcessor() {
|
||||
|
||||
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 (let decoratorName in decoratorMappings) {
|
||||
var propertyName = decoratorMappings[decoratorName];
|
||||
doc[propertyName] =
|
||||
getDecoratorValues(doc.directiveOptions[propertyName], decoratorName, doc.members);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
function getDecoratorValues(classDecoratorValues, memberDecoratorName, members) {
|
||||
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;
|
||||
}
|
||||
});
|
||||
|
||||
if (Object.keys(decoratorValues).length) {
|
||||
return decoratorValues;
|
||||
}
|
||||
}
|
81
aio/tools/transforms/angular-api-package/processors/mergeDecoratorDocs.js
vendored
Normal file
81
aio/tools/transforms/angular-api-package/processors/mergeDecoratorDocs.js
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
module.exports = function mergeDecoratorDocs(log) {
|
||||
return {
|
||||
$runAfter: ['processing-docs'],
|
||||
$runBefore: ['docs-processed'],
|
||||
makeDecoratorCalls: [
|
||||
{type: '', description: 'toplevel'},
|
||||
{type: 'Prop', description: 'property'},
|
||||
{type: 'Param', description: 'parameter'},
|
||||
],
|
||||
$process: function(docs) {
|
||||
|
||||
var makeDecoratorCalls = this.makeDecoratorCalls;
|
||||
var docsToMerge = Object.create(null);
|
||||
|
||||
docs.forEach(function(doc) {
|
||||
|
||||
makeDecoratorCalls.forEach(function(call) {
|
||||
// find all the decorators, signified by a call to `makeDecorator(metadata)`
|
||||
var makeDecorator = getMakeDecoratorCall(doc, call.type);
|
||||
if (makeDecorator) {
|
||||
log.debug('mergeDecoratorDocs: found decorator', doc.docType, doc.name);
|
||||
doc.docType = 'decorator';
|
||||
doc.decoratorLocation = call.description;
|
||||
// get the type of the decorator metadata
|
||||
doc.decoratorType = makeDecorator.arguments[0].text;
|
||||
// clear the symbol type named (e.g. ComponentMetadataFactory) since it is not needed
|
||||
doc.symbolTypeName = undefined;
|
||||
|
||||
// keep track of the names of the docs that need to be merged into this decorator doc
|
||||
docsToMerge[doc.name + 'Decorator'] = doc;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// merge the metadata docs into the decorator docs
|
||||
docs = docs.filter(function(doc) {
|
||||
if (docsToMerge[doc.name]) {
|
||||
var decoratorDoc = docsToMerge[doc.name];
|
||||
log.debug(
|
||||
'mergeDecoratorDocs: merging', doc.name, 'into', decoratorDoc.name,
|
||||
doc.callMember.description.substring(0, 50));
|
||||
decoratorDoc.description = doc.callMember.description;
|
||||
|
||||
// remove doc from its module doc's exports
|
||||
doc.moduleDoc.exports =
|
||||
doc.moduleDoc.exports.filter(function(exportDoc) { return exportDoc !== doc; });
|
||||
|
||||
|
||||
// remove from the overall list of docs to be rendered
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
function getMakeDecoratorCall(doc, type) {
|
||||
var makeDecoratorFnName = 'make' + (type || '') + 'Decorator';
|
||||
|
||||
var initializer = doc.exportSymbol && doc.exportSymbol.valueDeclaration &&
|
||||
doc.exportSymbol.valueDeclaration.initializer;
|
||||
|
||||
if (initializer) {
|
||||
// There appear to be two forms of initializer:
|
||||
// export var Injectable: InjectableFactory =
|
||||
// <InjectableFactory>makeDecorator(InjectableMetadata);
|
||||
// and
|
||||
// export var RouteConfig: (configs: RouteDefinition[]) => ClassDecorator =
|
||||
// makeDecorator(RouteConfigAnnotation);
|
||||
// In the first case, the type assertion `<InjectableFactory>` causes the AST to contain an
|
||||
// extra level of expression
|
||||
// to hold the new type of the expression.
|
||||
if (initializer.expression && initializer.expression.expression) {
|
||||
initializer = initializer.expression;
|
||||
}
|
||||
if (initializer.expression && initializer.expression.text === makeDecoratorFnName) {
|
||||
return initializer;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
var testPackage = require('../../helpers/test-package');
|
||||
var Dgeni = require('dgeni');
|
||||
|
||||
describe('mergeDecoratorDocs processor', function() {
|
||||
var dgeni, injector, processor, decoratorDoc, decoratorDocWithTypeAssertion, otherDoc;
|
||||
|
||||
beforeEach(function() {
|
||||
dgeni = new Dgeni([testPackage('angular-api-package')]);
|
||||
injector = dgeni.configureInjector();
|
||||
processor = injector.get('mergeDecoratorDocs');
|
||||
|
||||
decoratorDoc = {
|
||||
name: 'X',
|
||||
docType: 'var',
|
||||
exportSymbol: {
|
||||
valueDeclaration:
|
||||
{initializer: {expression: {text: 'makeDecorator'}, arguments: [{text: 'X'}]}}
|
||||
}
|
||||
};
|
||||
|
||||
decoratorDocWithTypeAssertion = {
|
||||
name: 'Y',
|
||||
docType: 'var',
|
||||
exportSymbol: {
|
||||
valueDeclaration: {
|
||||
initializer: {
|
||||
expression:
|
||||
{type: {}, expression: {text: 'makeDecorator'}, arguments: [{text: 'Y'}]}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
otherDoc = {
|
||||
name: 'Y',
|
||||
docType: 'var',
|
||||
exportSymbol: {
|
||||
valueDeclaration:
|
||||
{initializer: {expression: {text: 'otherCall'}, arguments: [{text: 'param1'}]}}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
it('should change the docType of only the docs that are initialied by a call to makeDecorator',
|
||||
function() {
|
||||
processor.$process([decoratorDoc, decoratorDocWithTypeAssertion, otherDoc]);
|
||||
expect(decoratorDoc.docType).toEqual('decorator');
|
||||
expect(decoratorDocWithTypeAssertion.docType).toEqual('decorator');
|
||||
expect(otherDoc.docType).toEqual('var');
|
||||
});
|
||||
|
||||
it('should extract the "type" of the decorator meta data', function() {
|
||||
processor.$process([decoratorDoc, decoratorDocWithTypeAssertion, otherDoc]);
|
||||
expect(decoratorDoc.decoratorType).toEqual('X');
|
||||
expect(decoratorDocWithTypeAssertion.decoratorType).toEqual('Y');
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user