build(aio): generate the api-list.json file from the API docs
This commit is contained in:
parent
7b6dbf0952
commit
eedca09d73
|
@ -10,15 +10,13 @@ import 'rxjs/add/operator/takeUntil';
|
||||||
import { Logger } from 'app/shared/logger.service';
|
import { Logger } from 'app/shared/logger.service';
|
||||||
|
|
||||||
export interface ApiItem {
|
export interface ApiItem {
|
||||||
|
name: string;
|
||||||
title: string;
|
title: string;
|
||||||
path: string;
|
path: string;
|
||||||
docType: string;
|
docType: string;
|
||||||
stability: string;
|
stability: string;
|
||||||
secure: string;
|
|
||||||
securityRisk: boolean;
|
securityRisk: boolean;
|
||||||
barrel: string;
|
|
||||||
|
|
||||||
name?: string;
|
|
||||||
show?: boolean;
|
show?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,14 +71,7 @@ export class ApiService implements OnDestroy {
|
||||||
const url = this.apiBase + (src || this.apiListJsonDefault);
|
const url = this.apiBase + (src || this.apiListJsonDefault);
|
||||||
this.http.get(url)
|
this.http.get(url)
|
||||||
.takeUntil(this.onDestroy)
|
.takeUntil(this.onDestroy)
|
||||||
.map(response => {
|
.map(response => response.json())
|
||||||
const sections = response.json();
|
|
||||||
return Object.keys(sections).map(title => {
|
|
||||||
const items = sections[title] as ApiItem[];
|
|
||||||
items.forEach(normalizeItem);
|
|
||||||
return { name: title.toLowerCase(), title, items };
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.do(() => this.logger.log(`Got API sections from ${url}`))
|
.do(() => this.logger.log(`Got API sections from ${url}`))
|
||||||
.subscribe(
|
.subscribe(
|
||||||
sections => this.sectionsSubject.next(sections),
|
sections => this.sectionsSubject.next(sections),
|
||||||
|
@ -90,16 +81,5 @@ export class ApiService implements OnDestroy {
|
||||||
throw err; // rethrow for now.
|
throw err; // rethrow for now.
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
function normalizeItem(item: ApiItem) {
|
|
||||||
item.name = item.title.toLowerCase();
|
|
||||||
// convert 'secure' property to boolean `securityRisk`
|
|
||||||
item.securityRisk = item.secure !== 'false';
|
|
||||||
// 'let' and 'var' doc types should be treated as 'const'
|
|
||||||
const docType = item.docType;
|
|
||||||
if (docType === 'let' || docType === 'var') {
|
|
||||||
item.docType = 'const';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -36,7 +36,7 @@ module.exports =
|
||||||
|
|
||||||
// Register the processors
|
// Register the processors
|
||||||
.processor(require('./processors/convertPrivateClassesToInterfaces'))
|
.processor(require('./processors/convertPrivateClassesToInterfaces'))
|
||||||
.processor(require('./processors/generateNavigationDoc'))
|
.processor(require('./processors/generateApiListDoc'))
|
||||||
.processor(require('./processors/generateKeywords'))
|
.processor(require('./processors/generateKeywords'))
|
||||||
.processor(require('./processors/createOverviewDump'))
|
.processor(require('./processors/createOverviewDump'))
|
||||||
.processor(require('./processors/checkUnbalancedBackTicks'))
|
.processor(require('./processors/checkUnbalancedBackTicks'))
|
||||||
|
@ -193,7 +193,7 @@ module.exports =
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// We are going to be relaxed about ambigous links
|
// We are not going to be relaxed about ambiguous links
|
||||||
.config(function(getLinkInfo) {
|
.config(function(getLinkInfo) {
|
||||||
getLinkInfo.useFirstAmbiguousLink = false;
|
getLinkInfo.useFirstAmbiguousLink = false;
|
||||||
})
|
})
|
||||||
|
@ -201,14 +201,14 @@ module.exports =
|
||||||
|
|
||||||
|
|
||||||
.config(function(
|
.config(function(
|
||||||
computeIdsProcessor, computePathsProcessor, EXPORT_DOC_TYPES, generateNavigationDoc,
|
computeIdsProcessor, computePathsProcessor, EXPORT_DOC_TYPES, generateApiListDoc,
|
||||||
generateKeywordsProcessor) {
|
generateKeywordsProcessor) {
|
||||||
|
|
||||||
const API_SEGMENT = 'api';
|
const API_SEGMENT = 'api';
|
||||||
const GUIDE_SEGMENT = 'guide';
|
const GUIDE_SEGMENT = 'guide';
|
||||||
const APP_SEGMENT = 'app';
|
const APP_SEGMENT = 'app';
|
||||||
|
|
||||||
generateNavigationDoc.outputFolder = APP_SEGMENT;
|
generateApiListDoc.outputFolder = API_SEGMENT;
|
||||||
generateKeywordsProcessor.outputFolder = APP_SEGMENT;
|
generateKeywordsProcessor.outputFolder = APP_SEGMENT;
|
||||||
|
|
||||||
// Replace any path templates inherited from other packages
|
// Replace any path templates inherited from other packages
|
||||||
|
@ -228,11 +228,6 @@ module.exports =
|
||||||
pathTemplate: '${moduleDoc.moduleFolder}/${name}',
|
pathTemplate: '${moduleDoc.moduleFolder}/${name}',
|
||||||
outputPathTemplate: '${moduleDoc.moduleFolder}/${name}.json',
|
outputPathTemplate: '${moduleDoc.moduleFolder}/${name}.json',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
docTypes: ['api-list-data', 'api-list-audit'],
|
|
||||||
pathTemplate: APP_SEGMENT + '/${docType}.json',
|
|
||||||
outputPathTemplate: '${path}'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
docTypes: ['cheatsheet-data'],
|
docTypes: ['cheatsheet-data'],
|
||||||
pathTemplate: GUIDE_SEGMENT + '/cheatsheet.json',
|
pathTemplate: GUIDE_SEGMENT + '/cheatsheet.json',
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
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.filter(doc => !doc.internal).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,151 @@
|
||||||
|
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.io-package')]);
|
||||||
|
const injector = dgeni.configureInjector();
|
||||||
|
const processor = injector.get('generateApiListDoc');
|
||||||
|
expect(processor.$process).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should run after "extra-docs-added"', () => {
|
||||||
|
const processor = processorFactory();
|
||||||
|
expect(processor.$runAfter).toEqual(['extra-docs-added']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should run before "rendering-docs"', () => {
|
||||||
|
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 exports', () => {
|
||||||
|
const processor = processorFactory();
|
||||||
|
const docs = [
|
||||||
|
{ docType: 'module', id: '@angular/common/index', exports: [
|
||||||
|
{ docType: 'directive', name: 'AaaAaa', path: 'aaa', internal: 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 },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
module.exports = function generateNavigationDoc() {
|
|
||||||
|
|
||||||
return {
|
|
||||||
$runAfter: ['extra-docs-added'],
|
|
||||||
$runBefore: ['rendering-docs'],
|
|
||||||
outputFolder: '',
|
|
||||||
$validate: {outputFolder: {presence: true}},
|
|
||||||
$process: function(docs) {
|
|
||||||
var modulesDoc = {
|
|
||||||
docType: 'data-module',
|
|
||||||
value: {api: {sections: []}, guide: {pages: []}},
|
|
||||||
path: this.outputFolder + '/navigation',
|
|
||||||
outputPath: this.outputFolder + '/navigation.ts',
|
|
||||||
serviceName: 'NAVIGATION'
|
|
||||||
};
|
|
||||||
|
|
||||||
docs.forEach(function(doc) {
|
|
||||||
if (doc.docType === 'module') {
|
|
||||||
var moduleNavItem =
|
|
||||||
{path: doc.path, partial: doc.outputPath, name: doc.id, type: 'module', pages: []};
|
|
||||||
|
|
||||||
modulesDoc.value.api.sections.push(moduleNavItem);
|
|
||||||
|
|
||||||
doc.exports.forEach(function(exportDoc) {
|
|
||||||
if (!exportDoc.internal) {
|
|
||||||
var exportNavItem = {
|
|
||||||
path: exportDoc.path,
|
|
||||||
partial: exportDoc.outputPath,
|
|
||||||
name: exportDoc.name,
|
|
||||||
type: exportDoc.docType
|
|
||||||
};
|
|
||||||
moduleNavItem.pages.push(exportNavItem);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
docs.forEach(function(doc) {
|
|
||||||
if (doc.docType === 'guide') {
|
|
||||||
console.log('guide', doc.name);
|
|
||||||
var guideDoc = {path: doc.path, partial: doc.outputPath, name: doc.name, type: 'guide'};
|
|
||||||
modulesDoc.value.guide.pages.push(guideDoc);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
docs.push(modulesDoc);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -1,15 +0,0 @@
|
||||||
[{% for module, items in doc.data %}
|
|
||||||
{% for item in items %}
|
|
||||||
{
|
|
||||||
"title": "{$ item.title $}",
|
|
||||||
"path": "{$ item.exportDoc.path $}",
|
|
||||||
"docType": "{$ item.docType $}",
|
|
||||||
"stability": "{$ item.stability $}",
|
|
||||||
"secure": "{$ item.security $}",
|
|
||||||
"howToUse": "{$ item.howToUse | replace('"','\\"') $}",
|
|
||||||
"whatItDoes": {% if item.whatItDoes %}"Exists"{% else %}"Not Done"{% endif %},
|
|
||||||
"barrel" : "{$ module | replace("/index", "") $}"
|
|
||||||
}{% if not loop.last %},{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% endfor %}
|
|
||||||
]
|
|
|
@ -1,14 +0,0 @@
|
||||||
{
|
|
||||||
{%- for module, items in doc.data %}
|
|
||||||
"{$ module | replace("/index", "") $}" : [{% for item in items %}
|
|
||||||
{
|
|
||||||
"title": "{$ item.title $}",
|
|
||||||
"path": "{$ item.exportDoc.path $}",
|
|
||||||
"docType": "{$ item.docType $}",
|
|
||||||
"stability": "{$ item.stability $}",
|
|
||||||
"secure": "{$ item.security $}",
|
|
||||||
"barrel" : "{$ module | replace("/index", "") $}"
|
|
||||||
}{% if not loop.last %},{% endif %}
|
|
||||||
{% endfor %}]{% if not loop.last %},{% endif %}
|
|
||||||
{% endfor -%}
|
|
||||||
}
|
|
Loading…
Reference in New Issue