build(docs-infra): implement the 'package' API template (#24631)
PR Close #24631
This commit is contained in:
parent
97277bc9fb
commit
d8c828c9b1
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
<article class="api-list-container l-content-small docs-content">
|
<article class="api-list-container l-content-small docs-content">
|
||||||
<div *ngFor="let section of filteredSections | async" >
|
<div *ngFor="let section of filteredSections | async" >
|
||||||
<h2>{{section.title}}</h2>
|
<h2><a [href]="section.path">{{section.title}}</a></h2>
|
||||||
<ul class="api-list">
|
<ul class="api-list">
|
||||||
<ng-container *ngFor="let item of section.items">
|
<ng-container *ngFor="let item of section.items">
|
||||||
<li *ngIf="item.show" class="api-item">
|
<li *ngIf="item.show" class="api-item">
|
||||||
|
|
|
@ -218,6 +218,7 @@ const apiSections: ApiSection[] = [
|
||||||
{
|
{
|
||||||
"name": "common",
|
"name": "common",
|
||||||
"title": "common",
|
"title": "common",
|
||||||
|
"path": "api/common",
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"name": "class_1",
|
"name": "class_1",
|
||||||
|
@ -256,6 +257,7 @@ const apiSections: ApiSection[] = [
|
||||||
{
|
{
|
||||||
"name": "core",
|
"name": "core",
|
||||||
"title": "core",
|
"title": "core",
|
||||||
|
"path": "api/core",
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"name": "class_3",
|
"name": "class_3",
|
||||||
|
|
|
@ -50,7 +50,7 @@ describe('ApiService', () => {
|
||||||
describe('#sections', () => {
|
describe('#sections', () => {
|
||||||
|
|
||||||
it('first subscriber should fetch sections', done => {
|
it('first subscriber should fetch sections', done => {
|
||||||
const data = [{name: 'a', title: 'A', items: []}, {name: 'b', title: 'B', items: []}];
|
const data = [{name: 'a', title: 'A', path: '', items: []}, {name: 'b', title: 'B', path: '', items: []}];
|
||||||
|
|
||||||
service.sections.subscribe(sections => {
|
service.sections.subscribe(sections => {
|
||||||
expect(sections).toEqual(data);
|
expect(sections).toEqual(data);
|
||||||
|
@ -61,7 +61,7 @@ describe('ApiService', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('second subscriber should get previous sections and NOT trigger refetch', done => {
|
it('second subscriber should get previous sections and NOT trigger refetch', done => {
|
||||||
const data = [{name: 'a', title: 'A', items: []}, {name: 'b', title: 'B', items: []}];
|
const data = [{name: 'a', title: 'A', path: '', items: []}, {name: 'b', title: 'B', path: '', items: []}];
|
||||||
let subscriptions = 0;
|
let subscriptions = 0;
|
||||||
|
|
||||||
service.sections.subscribe(sections => {
|
service.sections.subscribe(sections => {
|
||||||
|
@ -91,7 +91,7 @@ describe('ApiService', () => {
|
||||||
|
|
||||||
let call = 0;
|
let call = 0;
|
||||||
|
|
||||||
let data = [{name: 'a', title: 'A', items: []}, {name: 'b', title: 'B', items: []}];
|
let data = [{name: 'a', title: 'A', path: '', items: []}, {name: 'b', title: 'B', path: '', items: []}];
|
||||||
|
|
||||||
service.sections.subscribe(sections => {
|
service.sections.subscribe(sections => {
|
||||||
// called twice during this test
|
// called twice during this test
|
||||||
|
@ -103,7 +103,7 @@ describe('ApiService', () => {
|
||||||
httpMock.expectOne({}).flush(data);
|
httpMock.expectOne({}).flush(data);
|
||||||
|
|
||||||
// refresh/refetch
|
// refresh/refetch
|
||||||
data = [{name: 'c', title: 'C', items: []}];
|
data = [{name: 'c', title: 'C', path: '', items: []}];
|
||||||
service.fetchSections();
|
service.fetchSections();
|
||||||
httpMock.expectOne({}).flush(data);
|
httpMock.expectOne({}).flush(data);
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ export interface ApiItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ApiSection {
|
export interface ApiSection {
|
||||||
|
path: string;
|
||||||
name: string;
|
name: string;
|
||||||
title: string;
|
title: string;
|
||||||
items: ApiItem[];
|
items: ApiItem[];
|
||||||
|
|
|
@ -28,7 +28,7 @@ h2 {
|
||||||
h3 {
|
h3 {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
margin: 24px 0px;
|
margin: 24px 0px 12px;
|
||||||
clear: both;
|
clear: both;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +55,10 @@ h6 {
|
||||||
}
|
}
|
||||||
|
|
||||||
h2, h3, h4, h5, h6 {
|
h2, h3, h4, h5, h6 {
|
||||||
|
a {
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 600px) {
|
@media screen and (max-width: 600px) {
|
||||||
margin: 8px 0;
|
margin: 8px 0;
|
||||||
}
|
}
|
||||||
|
@ -105,7 +109,7 @@ table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
border-spacing: 0;
|
border-spacing: 0;
|
||||||
margin: 0 0 32px 0;
|
margin: 12px 0 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
table tbody th {
|
table tbody th {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
max-width: 1200px;
|
max-width: 1200px;
|
||||||
|
|
||||||
table {
|
table {
|
||||||
|
margin: 12px 0 24px;
|
||||||
|
|
||||||
th {
|
th {
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.method-table, .option-table {
|
.method-table, .option-table, .list-table {
|
||||||
th {
|
th {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
@ -105,7 +105,7 @@ $api-symbols: (
|
||||||
content: 'T',
|
content: 'T',
|
||||||
background: $light-green-600
|
background: $light-green-600
|
||||||
),
|
),
|
||||||
module: (
|
package: (
|
||||||
content: 'Pk',
|
content: 'Pk',
|
||||||
background: $purple-600
|
background: $purple-600
|
||||||
)
|
)
|
||||||
|
|
|
@ -33,6 +33,7 @@ module.exports = new Package('angular-api', [basePackage, typeScriptPackage])
|
||||||
.processor(require('./processors/simplifyMemberAnchors'))
|
.processor(require('./processors/simplifyMemberAnchors'))
|
||||||
.processor(require('./processors/computeStability'))
|
.processor(require('./processors/computeStability'))
|
||||||
.processor(require('./processors/removeInjectableConstructors'))
|
.processor(require('./processors/removeInjectableConstructors'))
|
||||||
|
.processor(require('./processors/processPackages'))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* These are the API doc types that will be rendered to actual files.
|
* These are the API doc types that will be rendered to actual files.
|
||||||
|
@ -40,7 +41,7 @@ module.exports = new Package('angular-api', [basePackage, typeScriptPackage])
|
||||||
* more Angular specific API types, such as decorators and directives.
|
* more Angular specific API types, such as decorators and directives.
|
||||||
*/
|
*/
|
||||||
.factory(function API_DOC_TYPES_TO_RENDER(EXPORT_DOC_TYPES) {
|
.factory(function API_DOC_TYPES_TO_RENDER(EXPORT_DOC_TYPES) {
|
||||||
return EXPORT_DOC_TYPES.concat(['decorator', 'directive', 'pipe', 'module']);
|
return EXPORT_DOC_TYPES.concat(['decorator', 'directive', 'pipe', 'package']);
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,8 +59,10 @@ module.exports = new Package('angular-api', [basePackage, typeScriptPackage])
|
||||||
return API_DOC_TYPES_TO_RENDER.concat(API_CONTAINED_DOC_TYPES);
|
return API_DOC_TYPES_TO_RENDER.concat(API_CONTAINED_DOC_TYPES);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
.factory(require('./readers/package-content'))
|
||||||
|
|
||||||
// Where do we get the source files?
|
// Where do we get the source files?
|
||||||
.config(function(readTypeScriptModules, readFilesProcessor, collectExamples, tsParser) {
|
.config(function(readTypeScriptModules, readFilesProcessor, collectExamples, tsParser, packageContentFileReader) {
|
||||||
|
|
||||||
// Tell TypeScript how to load modules that start with with `@angular`
|
// Tell TypeScript how to load modules that start with with `@angular`
|
||||||
tsParser.options.paths = { '@angular/*': [API_SOURCE_PATH + '/*'] };
|
tsParser.options.paths = { '@angular/*': [API_SOURCE_PATH + '/*'] };
|
||||||
|
@ -102,12 +105,19 @@ module.exports = new Package('angular-api', [basePackage, typeScriptPackage])
|
||||||
'upgrade/static/index.ts',
|
'upgrade/static/index.ts',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
readFilesProcessor.fileReaders.push(packageContentFileReader);
|
||||||
|
|
||||||
// API Examples
|
// API Examples
|
||||||
readFilesProcessor.sourceFiles = [
|
readFilesProcessor.sourceFiles = [
|
||||||
{
|
{
|
||||||
basePath: API_SOURCE_PATH,
|
basePath: API_SOURCE_PATH,
|
||||||
include: API_SOURCE_PATH + '/examples/**/*',
|
include: API_SOURCE_PATH + '/examples/**/*',
|
||||||
fileReader: 'exampleFileReader'
|
fileReader: 'exampleFileReader'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
basePath: API_SOURCE_PATH,
|
||||||
|
include: API_SOURCE_PATH + '/**/PACKAGE.md',
|
||||||
|
fileReader: 'packageContentFileReader'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
collectExamples.exampleFolders.push('examples');
|
collectExamples.exampleFolders.push('examples');
|
||||||
|
@ -123,7 +133,7 @@ module.exports = new Package('angular-api', [basePackage, typeScriptPackage])
|
||||||
.config(function(computeStability, splitDescription, addNotYetDocumentedProperty, API_DOC_TYPES_TO_RENDER, API_DOC_TYPES) {
|
.config(function(computeStability, splitDescription, addNotYetDocumentedProperty, API_DOC_TYPES_TO_RENDER, API_DOC_TYPES) {
|
||||||
computeStability.docTypes = API_DOC_TYPES_TO_RENDER;
|
computeStability.docTypes = API_DOC_TYPES_TO_RENDER;
|
||||||
// Only split the description on the API docs
|
// Only split the description on the API docs
|
||||||
splitDescription.docTypes = API_DOC_TYPES;
|
splitDescription.docTypes = API_DOC_TYPES.concat(['package-content']);
|
||||||
addNotYetDocumentedProperty.docTypes = API_DOC_TYPES;
|
addNotYetDocumentedProperty.docTypes = API_DOC_TYPES;
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -180,7 +190,7 @@ module.exports = new Package('angular-api', [basePackage, typeScriptPackage])
|
||||||
generateApiListDoc.outputFolder = API_SEGMENT;
|
generateApiListDoc.outputFolder = API_SEGMENT;
|
||||||
|
|
||||||
computePathsProcessor.pathTemplates.push({
|
computePathsProcessor.pathTemplates.push({
|
||||||
docTypes: ['module'],
|
docTypes: ['package'],
|
||||||
getPath: function computeModulePath(doc) {
|
getPath: function computeModulePath(doc) {
|
||||||
doc.moduleFolder = `${API_SEGMENT}/${doc.id.replace(/\/index$/, '')}`;
|
doc.moduleFolder = `${API_SEGMENT}/${doc.id.replace(/\/index$/, '')}`;
|
||||||
return doc.moduleFolder;
|
return doc.moduleFolder;
|
||||||
|
|
|
@ -33,7 +33,7 @@ describe('addSelectorsAsAliases processor', () => {
|
||||||
{ docType: 'directive', name: 'NgModel', aliases: ['NgModel'], directiveOptions: { selector: '\'[ngModel]:not([formControlName]):not([formControl])\'' } },
|
{ docType: 'directive', name: 'NgModel', aliases: ['NgModel'], directiveOptions: { selector: '\'[ngModel]:not([formControlName]):not([formControl])\'' } },
|
||||||
{ docType: 'component', name: 'MyComponent', aliases: ['MyComponent'], componentOptions: { selector: '\'my-component\'' } },
|
{ docType: 'component', name: 'MyComponent', aliases: ['MyComponent'], componentOptions: { selector: '\'my-component\'' } },
|
||||||
{ docType: 'decorator', name: 'MyDecorator', aliases: ['MyDecorator'] },
|
{ docType: 'decorator', name: 'MyDecorator', aliases: ['MyDecorator'] },
|
||||||
{ docType: 'module', name: 'myModule', aliases: ['myModule'], id: 'some/myModule' },
|
{ docType: 'package', name: 'myPackage', aliases: ['myPackage'], id: 'some/myPackage' },
|
||||||
{ docType: 'var', name: 'myVar', aliases: ['myVar'] },
|
{ docType: 'var', name: 'myVar', aliases: ['myVar'] },
|
||||||
{ docType: 'let', name: 'myLet', aliases: ['myLet'] },
|
{ docType: 'let', name: 'myLet', aliases: ['myLet'] },
|
||||||
{ docType: 'const', name: 'myConst', aliases: ['myConst'] },
|
{ docType: 'const', name: 'myConst', aliases: ['myConst'] },
|
||||||
|
|
|
@ -14,14 +14,14 @@ describe('angular-api-package: computeApiBreadCrumbs processor', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should attach a breadCrumbs property to each of the API_DOC_TYPES_TO_RENDER docs', () => {
|
it('should attach a breadCrumbs property to each of the API_DOC_TYPES_TO_RENDER docs', () => {
|
||||||
const API_DOC_TYPES_TO_RENDER = ['class', 'interface', 'module'];
|
const API_DOC_TYPES_TO_RENDER = ['class', 'interface', 'package'];
|
||||||
const processor = processorFactory(API_DOC_TYPES_TO_RENDER);
|
const processor = processorFactory(API_DOC_TYPES_TO_RENDER);
|
||||||
|
|
||||||
const docs = [
|
const docs = [
|
||||||
{ docType: 'class', name: 'ClassA', path: 'module-1/class-a', moduleDoc: { id: 'moduleOne', path: 'module-1' } },
|
{ docType: 'class', name: 'ClassA', path: 'module-1/class-a', moduleDoc: { id: 'moduleOne', path: 'module-1' } },
|
||||||
{ docType: 'interface', name: 'InterfaceB', path: 'module-2/interface-b', moduleDoc: { id: 'moduleTwo', path: 'module-2' } },
|
{ docType: 'interface', name: 'InterfaceB', path: 'module-2/interface-b', moduleDoc: { id: 'moduleTwo', path: 'module-2' } },
|
||||||
{ docType: 'guide', name: 'Guide One', path: 'guide/guide-1' },
|
{ docType: 'guide', name: 'Guide One', path: 'guide/guide-1' },
|
||||||
{ docType: 'module', name: 'testing', id: 'http/testing', path: 'http/testing' },
|
{ docType: 'package', name: 'testing', id: 'http/testing', path: 'http/testing' },
|
||||||
];
|
];
|
||||||
processor.$process(docs);
|
processor.$process(docs);
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ module.exports = function computeSearchTitleProcessor() {
|
||||||
case 'function':
|
case 'function':
|
||||||
doc.searchTitle = `${doc.name}()`;
|
doc.searchTitle = `${doc.name}()`;
|
||||||
break;
|
break;
|
||||||
case 'module':
|
case 'package':
|
||||||
doc.searchTitle = `${doc.id} package`;
|
doc.searchTitle = `${doc.id} package`;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ describe('computeSearchTitle processor', () => {
|
||||||
{ docType: 'pipe', name: 'MyPipe', pipeOptions: { name: 'myPipe' } },
|
{ docType: 'pipe', name: 'MyPipe', pipeOptions: { name: 'myPipe' } },
|
||||||
{ docType: 'directive', name: 'MyDirective', directiveOptions: {} },
|
{ docType: 'directive', name: 'MyDirective', directiveOptions: {} },
|
||||||
{ docType: 'decorator', name: 'MyDecorator' },
|
{ docType: 'decorator', name: 'MyDecorator' },
|
||||||
{ docType: 'module', name: 'myModule', id: 'some/myModule' },
|
{ docType: 'package', name: 'myPackage', id: 'some/myPackage' },
|
||||||
{ docType: 'var', name: 'myVar' },
|
{ docType: 'var', name: 'myVar' },
|
||||||
{ docType: 'let', name: 'myLet' },
|
{ docType: 'let', name: 'myLet' },
|
||||||
{ docType: 'const', name: 'myConst' },
|
{ docType: 'const', name: 'myConst' },
|
||||||
|
@ -45,7 +45,7 @@ describe('computeSearchTitle processor', () => {
|
||||||
expect(docs[4].searchTitle).toBeUndefined();
|
expect(docs[4].searchTitle).toBeUndefined();
|
||||||
expect(docs[5].searchTitle).toBeUndefined();
|
expect(docs[5].searchTitle).toBeUndefined();
|
||||||
expect(docs[6].searchTitle).toBeUndefined();
|
expect(docs[6].searchTitle).toBeUndefined();
|
||||||
expect(docs[7].searchTitle).toEqual('some/myModule package');
|
expect(docs[7].searchTitle).toEqual('some/myPackage package');
|
||||||
expect(docs[8].searchTitle).toBeUndefined();
|
expect(docs[8].searchTitle).toBeUndefined();
|
||||||
expect(docs[9].searchTitle).toBeUndefined();
|
expect(docs[9].searchTitle).toBeUndefined();
|
||||||
expect(docs[10].searchTitle).toBeUndefined();
|
expect(docs[10].searchTitle).toBeUndefined();
|
||||||
|
|
|
@ -12,19 +12,20 @@ module.exports = function generateApiListDoc() {
|
||||||
path: this.outputFolder + '/api-list.json',
|
path: this.outputFolder + '/api-list.json',
|
||||||
outputPath: this.outputFolder + '/api-list.json',
|
outputPath: this.outputFolder + '/api-list.json',
|
||||||
data: docs
|
data: docs
|
||||||
.filter(doc => doc.docType === 'module')
|
.filter(doc => doc.docType === 'package')
|
||||||
.map(getModuleInfo)
|
.map(getPackageInfo)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
function getModuleInfo(moduleDoc) {
|
function getPackageInfo(packageDoc) {
|
||||||
const moduleName = moduleDoc.id.replace(/\/index$/, '');
|
const packageName = packageDoc.id.replace(/\/index$/, '');
|
||||||
return {
|
return {
|
||||||
name: moduleName.toLowerCase(),
|
name: packageName.toLowerCase(),
|
||||||
title: moduleName,
|
title: packageName,
|
||||||
items: moduleDoc.exports
|
path: packageDoc.path,
|
||||||
|
items: packageDoc.exports
|
||||||
// Ignore internals and private exports (indicated by the ɵ prefix)
|
// Ignore internals and private exports (indicated by the ɵ prefix)
|
||||||
.filter(doc => !doc.internal && !doc.privateExport)
|
.filter(doc => !doc.internal && !doc.privateExport)
|
||||||
.map(getExportInfo)
|
.map(getExportInfo)
|
||||||
|
|
|
@ -38,28 +38,28 @@ describe('generateApiListDoc processor', () => {
|
||||||
it('should add an info object to the doc for each module doc', () => {
|
it('should add an info object to the doc for each module doc', () => {
|
||||||
const processor = processorFactory();
|
const processor = processorFactory();
|
||||||
const docs = [
|
const docs = [
|
||||||
{ docType: 'module', id: '@angular/common/index', exports: [] },
|
{ docType: 'package', id: '@angular/common/index', exports: [], path: 'common' },
|
||||||
{ docType: 'module', id: '@angular/core/index', exports: [] },
|
{ docType: 'package', id: '@angular/core/index', exports: [], path: 'core' },
|
||||||
{ docType: 'module', id: '@angular/http/index', exports: [] },
|
{ docType: 'package', id: '@angular/http/index', exports: [], path: 'http' },
|
||||||
];
|
];
|
||||||
processor.$process(docs);
|
processor.$process(docs);
|
||||||
expect(docs[3].data).toEqual([
|
expect(docs[3].data).toEqual([
|
||||||
{ name: '@angular/common', title: '@angular/common', items: [] },
|
{ name: '@angular/common', title: '@angular/common', items: [], path: 'common' },
|
||||||
{ name: '@angular/core', title: '@angular/core', items: [] },
|
{ name: '@angular/core', title: '@angular/core', items: [], path: 'core' },
|
||||||
{ name: '@angular/http', title: '@angular/http', items: [] },
|
{ name: '@angular/http', title: '@angular/http', items: [], path: 'http' },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add info about each export on each module', () => {
|
it('should add info about each export on each module', () => {
|
||||||
const processor = processorFactory();
|
const processor = processorFactory();
|
||||||
const docs = [
|
const docs = [
|
||||||
{ docType: 'module', id: '@angular/common/index', exports: [
|
{ docType: 'package', id: '@angular/common/index', exports: [
|
||||||
{ docType: 'directive', name: 'AaaAaa', path: 'aaa' },
|
{ docType: 'directive', name: 'AaaAaa', path: 'aaa' },
|
||||||
{ docType: 'pipe', name: 'BbbBbb', path: 'bbb' },
|
{ docType: 'pipe', name: 'BbbBbb', path: 'bbb' },
|
||||||
{ docType: 'decorator', name: 'CccCcc', path: 'ccc' },
|
{ docType: 'decorator', name: 'CccCcc', path: 'ccc' },
|
||||||
{ docType: 'class', name: 'DddDdd', path: 'ddd' }
|
{ docType: 'class', name: 'DddDdd', path: 'ddd' }
|
||||||
] },
|
] },
|
||||||
{ docType: 'module', id: '@angular/core/index', exports: [
|
{ docType: 'package', id: '@angular/core/index', exports: [
|
||||||
{ docType: 'interface', name: 'EeeEee', path: 'eee' },
|
{ docType: 'interface', name: 'EeeEee', path: 'eee' },
|
||||||
{ docType: 'function', name: 'FffFff', path: 'fff' },
|
{ docType: 'function', name: 'FffFff', path: 'fff' },
|
||||||
{ docType: 'enum', name: 'GggGgg', path: 'ggg' },
|
{ docType: 'enum', name: 'GggGgg', path: 'ggg' },
|
||||||
|
@ -86,7 +86,7 @@ describe('generateApiListDoc processor', () => {
|
||||||
it('should ignore internal and private exports', () => {
|
it('should ignore internal and private exports', () => {
|
||||||
const processor = processorFactory();
|
const processor = processorFactory();
|
||||||
const docs = [
|
const docs = [
|
||||||
{ docType: 'module', id: '@angular/common/index', exports: [
|
{ docType: 'package', id: '@angular/common/index', exports: [
|
||||||
{ docType: 'directive', name: 'AaaAaa', path: 'aaa', internal: true },
|
{ docType: 'directive', name: 'AaaAaa', path: 'aaa', internal: true },
|
||||||
{ docType: 'class', name: 'XxxXxx', path: 'xxx', privateExport: true },
|
{ docType: 'class', name: 'XxxXxx', path: 'xxx', privateExport: true },
|
||||||
{ docType: 'pipe', name: 'BbbBbb', path: 'bbb' }
|
{ docType: 'pipe', name: 'BbbBbb', path: 'bbb' }
|
||||||
|
@ -101,7 +101,7 @@ describe('generateApiListDoc processor', () => {
|
||||||
it('should convert `let` and `var` docTypes to `const`', () => {
|
it('should convert `let` and `var` docTypes to `const`', () => {
|
||||||
const processor = processorFactory();
|
const processor = processorFactory();
|
||||||
const docs = [
|
const docs = [
|
||||||
{ docType: 'module', id: '@angular/common/index', exports: [
|
{ docType: 'package', id: '@angular/common/index', exports: [
|
||||||
{ docType: 'var', name: 'AaaAaa', path: 'aaa' },
|
{ docType: 'var', name: 'AaaAaa', path: 'aaa' },
|
||||||
{ docType: 'let', name: 'BbbBbb', path: 'bbb' },
|
{ docType: 'let', name: 'BbbBbb', path: 'bbb' },
|
||||||
]}
|
]}
|
||||||
|
@ -116,7 +116,7 @@ describe('generateApiListDoc processor', () => {
|
||||||
it('should convert security to a boolean securityRisk', () => {
|
it('should convert security to a boolean securityRisk', () => {
|
||||||
const processor = processorFactory();
|
const processor = processorFactory();
|
||||||
const docs = [
|
const docs = [
|
||||||
{ docType: 'module', id: '@angular/common/index', exports: [
|
{ docType: 'package', id: '@angular/common/index', exports: [
|
||||||
{ docType: 'class', name: 'AaaAaa', path: 'aaa', security: 'This is a security risk' },
|
{ docType: 'class', name: 'AaaAaa', path: 'aaa', security: 'This is a security risk' },
|
||||||
{ docType: 'class', name: 'BbbBbb', path: 'bbb', security: '' },
|
{ docType: 'class', name: 'BbbBbb', path: 'bbb', security: '' },
|
||||||
]}
|
]}
|
||||||
|
@ -131,7 +131,7 @@ describe('generateApiListDoc processor', () => {
|
||||||
it('should convert stability tags to the stable string property', () => {
|
it('should convert stability tags to the stable string property', () => {
|
||||||
const processor = processorFactory();
|
const processor = processorFactory();
|
||||||
const docs = [
|
const docs = [
|
||||||
{ docType: 'module', id: '@angular/common/index', exports: [
|
{ docType: 'package', id: '@angular/common/index', exports: [
|
||||||
{ docType: 'class', name: 'AaaAaa', path: 'aaa', stable: undefined },
|
{ docType: 'class', name: 'AaaAaa', path: 'aaa', stable: undefined },
|
||||||
{ docType: 'class', name: 'BbbBbb', path: 'bbb', experimental: 'Some message' },
|
{ docType: 'class', name: 'BbbBbb', path: 'bbb', experimental: 'Some message' },
|
||||||
{ docType: 'class', name: 'CccCcc', path: 'ccc', deprecated: null },
|
{ docType: 'class', name: 'CccCcc', path: 'ccc', deprecated: null },
|
||||||
|
@ -150,7 +150,7 @@ describe('generateApiListDoc processor', () => {
|
||||||
it('should sort items in each group alphabetically', () => {
|
it('should sort items in each group alphabetically', () => {
|
||||||
const processor = processorFactory();
|
const processor = processorFactory();
|
||||||
const docs = [
|
const docs = [
|
||||||
{ docType: 'module', id: '@angular/common/index', exports: [
|
{ docType: 'package', id: '@angular/common/index', exports: [
|
||||||
{ docType: 'class', name: 'DddDdd', path: 'uuu' },
|
{ docType: 'class', name: 'DddDdd', path: 'uuu' },
|
||||||
{ docType: 'class', name: 'BbbBbb', path: 'vvv' },
|
{ docType: 'class', name: 'BbbBbb', path: 'vvv' },
|
||||||
{ docType: 'class', name: 'AaaAaa', path: 'xxx' },
|
{ docType: 'class', name: 'AaaAaa', path: 'xxx' },
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
const { dirname } = require('canonical-path');
|
||||||
|
|
||||||
|
module.exports = function processPackages() {
|
||||||
|
return {
|
||||||
|
$runAfter: ['extractDecoratedClassesProcessor'],
|
||||||
|
$runBefore: ['computing-ids'],
|
||||||
|
$process(docs) {
|
||||||
|
const packageContentFiles = {};
|
||||||
|
const packageMap = {};
|
||||||
|
|
||||||
|
docs = docs.filter(doc => {
|
||||||
|
if (doc.docType === 'package-content') {
|
||||||
|
packageContentFiles[dirname(doc.fileInfo.filePath)] = doc;
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
docs.forEach(doc => {
|
||||||
|
if (doc.docType === 'module') {
|
||||||
|
// Convert the doc type from "module" to "package"
|
||||||
|
doc.docType = 'package';
|
||||||
|
// The name is actually the full id
|
||||||
|
doc.name = `@angular/${doc.id}`;
|
||||||
|
|
||||||
|
// Partition the exports into groups by type
|
||||||
|
if (doc.exports) {
|
||||||
|
doc.classes = doc.exports.filter(doc => doc.docType === 'class');
|
||||||
|
doc.decorators = doc.exports.filter(doc => doc.docType === 'decorator');
|
||||||
|
doc.functions = doc.exports.filter(doc => doc.docType === 'function');
|
||||||
|
doc.structures = doc.exports.filter(doc => doc.docType === 'enum' || doc.docType === 'interface');
|
||||||
|
doc.directives = doc.exports.filter(doc => doc.docType === 'directive');
|
||||||
|
doc.pipes = doc.exports.filter(doc => doc.docType === 'pipe');
|
||||||
|
doc.types = doc.exports.filter(doc => doc.docType === 'type-alias' || doc.docType === 'const');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy over docs from the PACKAGE.md file that is used to document packages
|
||||||
|
const readmeDoc = packageContentFiles[dirname(doc.fileInfo.filePath)];
|
||||||
|
if (readmeDoc) {
|
||||||
|
doc.shortDescription = readmeDoc.shortDescription;
|
||||||
|
doc.description = readmeDoc.description;
|
||||||
|
doc.see = readmeDoc.see;
|
||||||
|
doc.fileInfo = readmeDoc.fileInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute the primary/secondary entry point relationships
|
||||||
|
const packageParts = doc.id.split('/');
|
||||||
|
const primaryPackageName = packageParts[0];
|
||||||
|
doc.isPrimaryPackage = packageParts.length === 1;
|
||||||
|
doc.packageInfo = packageMap[primaryPackageName] = packageMap[primaryPackageName] || { primary: undefined, secondary: [] };
|
||||||
|
if (doc.isPrimaryPackage) {
|
||||||
|
doc.packageInfo.primary = doc;
|
||||||
|
} else {
|
||||||
|
doc.packageInfo.secondary.push(doc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return docs;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,180 @@
|
||||||
|
const testPackage = require('../../helpers/test-package');
|
||||||
|
const processorFactory = require('./processPackages');
|
||||||
|
const Dgeni = require('dgeni');
|
||||||
|
|
||||||
|
describe('processPackages processor', () => {
|
||||||
|
|
||||||
|
it('should be available on the injector', () => {
|
||||||
|
const dgeni = new Dgeni([testPackage('angular-api-package')]);
|
||||||
|
const injector = dgeni.configureInjector();
|
||||||
|
const processor = injector.get('processPackages');
|
||||||
|
expect(processor.$process).toBeDefined();
|
||||||
|
expect(processor.$runAfter).toEqual(['extractDecoratedClassesProcessor']);
|
||||||
|
expect(processor.$runBefore).toEqual(['computing-ids']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should filter out any `package-content` docs from the collection', () => {
|
||||||
|
const docs = [
|
||||||
|
{ fileInfo: { filePath: 'some/a' }, docType: 'a', id: 'a' },
|
||||||
|
{ fileInfo: { filePath: 'some/x' }, docType: 'package-content', id: 'x' },
|
||||||
|
{ fileInfo: { filePath: 'some/b' }, docType: 'b', id: 'b' },
|
||||||
|
{ fileInfo: { filePath: 'some/y' }, docType: 'package-content', id: 'y' },
|
||||||
|
{ fileInfo: { filePath: 'some/z' }, docType: 'package-content', id: 'z' },
|
||||||
|
];
|
||||||
|
const processor = processorFactory();
|
||||||
|
const newDocs = processor.$process(docs);
|
||||||
|
expect(newDocs).toEqual([
|
||||||
|
{ fileInfo: { filePath: 'some/a' }, docType: 'a', id: 'a' },
|
||||||
|
{ fileInfo: { filePath: 'some/b' }, docType: 'b', id: 'b' },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should change `module` docs to `package` docs', () => {
|
||||||
|
const processor = processorFactory();
|
||||||
|
const docs = [
|
||||||
|
{ fileInfo: { filePath: 'some/a' }, docType: 'module', id: 'a' },
|
||||||
|
{ fileInfo: { filePath: 'some/b' }, docType: 'module', id: 'b' },
|
||||||
|
{ docType: 'other', id: 'c' },
|
||||||
|
];
|
||||||
|
const newDocs = processor.$process(docs);
|
||||||
|
expect(newDocs).toEqual([
|
||||||
|
jasmine.objectContaining({ docType: 'package', id: 'a' }),
|
||||||
|
jasmine.objectContaining({ docType: 'package', id: 'b' }),
|
||||||
|
jasmine.objectContaining({ docType: 'other', id: 'c' }),
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should attach the relevant package contents to the package doc', () => {
|
||||||
|
const docs = [
|
||||||
|
{
|
||||||
|
fileInfo: { filePath: 'some/package-1/index' },
|
||||||
|
docType: 'module',
|
||||||
|
id: 'package-1',
|
||||||
|
someProp: 'foo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fileInfo: { filePath: 'some/package-1/PACKAGE.md' },
|
||||||
|
docType: 'package-content',
|
||||||
|
id: 'package-1/PACKAGE.md',
|
||||||
|
shortDescription: 'some short description',
|
||||||
|
description: 'some description',
|
||||||
|
see: [ 'a', 'b' ],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fileInfo: { filePath: 'some/package-2/index' },
|
||||||
|
docType: 'module',
|
||||||
|
id: 'package-2',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const processor = processorFactory();
|
||||||
|
const newDocs = processor.$process(docs);
|
||||||
|
|
||||||
|
const package1 = jasmine.objectContaining({
|
||||||
|
fileInfo: { filePath: 'some/package-1/PACKAGE.md' },
|
||||||
|
docType: 'package',
|
||||||
|
name: '@angular/package-1',
|
||||||
|
id: 'package-1',
|
||||||
|
someProp: 'foo',
|
||||||
|
shortDescription: 'some short description',
|
||||||
|
description: 'some description',
|
||||||
|
see: [ 'a', 'b' ],
|
||||||
|
isPrimaryPackage: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const package2 = jasmine.objectContaining({
|
||||||
|
fileInfo: { filePath: 'some/package-2/index' },
|
||||||
|
docType: 'package',
|
||||||
|
name: '@angular/package-2',
|
||||||
|
id: 'package-2',
|
||||||
|
isPrimaryPackage: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(newDocs).toEqual([package1, package2]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should compute primary and second package info', () => {
|
||||||
|
const docs = [
|
||||||
|
{
|
||||||
|
fileInfo: { filePath: 'some/package-1/index' },
|
||||||
|
docType: 'module',
|
||||||
|
id: 'package-1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fileInfo: { filePath: 'some/package-1/sub-1index' },
|
||||||
|
docType: 'module',
|
||||||
|
id: 'package-1/sub-1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fileInfo: { filePath: 'some/package-1/sub-2index' },
|
||||||
|
docType: 'module',
|
||||||
|
id: 'package-1/sub-2',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const processor = processorFactory();
|
||||||
|
const newDocs = processor.$process(docs);
|
||||||
|
|
||||||
|
expect(newDocs[0].isPrimaryPackage).toBe(true);
|
||||||
|
expect(newDocs[1].isPrimaryPackage).toBe(false);
|
||||||
|
expect(newDocs[2].isPrimaryPackage).toBe(false);
|
||||||
|
|
||||||
|
expect(newDocs[0].packageInfo.primary).toBe(newDocs[0]);
|
||||||
|
expect(newDocs[1].packageInfo.primary).toBe(newDocs[0]);
|
||||||
|
expect(newDocs[2].packageInfo.primary).toBe(newDocs[0]);
|
||||||
|
|
||||||
|
expect(newDocs[0].packageInfo.secondary).toEqual([newDocs[1], newDocs[2]]);
|
||||||
|
expect(newDocs[1].packageInfo.secondary).toEqual([newDocs[1], newDocs[2]]);
|
||||||
|
expect(newDocs[2].packageInfo.secondary).toEqual([newDocs[1], newDocs[2]]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should partition the exports of packages into groups', () => {
|
||||||
|
const docs = [
|
||||||
|
{
|
||||||
|
fileInfo: { filePath: 'some/x' },
|
||||||
|
docType: 'module',
|
||||||
|
id: 'x',
|
||||||
|
exports: [
|
||||||
|
{ docType: 'directive', id: 'directive-1' },
|
||||||
|
{ docType: 'function', id: 'function-1' },
|
||||||
|
{ docType: 'directive', id: 'directive-2' },
|
||||||
|
{ docType: 'decorator', id: 'decorator-1' },
|
||||||
|
{ docType: 'class', id: 'class-1' },
|
||||||
|
{ docType: 'type-alias', id: 'type-alias-1' },
|
||||||
|
{ docType: 'class', id: 'class-2' },
|
||||||
|
{ docType: 'pipe', id: 'pipe-1' },
|
||||||
|
{ docType: 'const', id: 'const-1' },
|
||||||
|
{ docType: 'const', id: 'const-2' },
|
||||||
|
{ docType: 'enum', id: 'enum-1' },
|
||||||
|
{ docType: 'interface', id: 'interface-1' },
|
||||||
|
{ docType: 'interface', id: 'interface-2' },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const processor = processorFactory();
|
||||||
|
const newDocs = processor.$process(docs);
|
||||||
|
|
||||||
|
expect(newDocs[0].decorators).toEqual([
|
||||||
|
{ docType: 'decorator', id: 'decorator-1' },
|
||||||
|
]);
|
||||||
|
expect(newDocs[0].functions).toEqual([
|
||||||
|
{ docType: 'function', id: 'function-1' },
|
||||||
|
]);
|
||||||
|
expect(newDocs[0].structures).toEqual([
|
||||||
|
{ docType: 'enum', id: 'enum-1' },
|
||||||
|
{ docType: 'interface', id: 'interface-1' },
|
||||||
|
{ docType: 'interface', id: 'interface-2' },
|
||||||
|
]);
|
||||||
|
expect(newDocs[0].directives).toEqual([
|
||||||
|
{ docType: 'directive', id: 'directive-1' },
|
||||||
|
{ docType: 'directive', id: 'directive-2' },
|
||||||
|
]);
|
||||||
|
expect(newDocs[0].pipes).toEqual([
|
||||||
|
{ docType: 'pipe', id: 'pipe-1' },
|
||||||
|
]);
|
||||||
|
expect(newDocs[0].types).toEqual([
|
||||||
|
{ docType: 'type-alias', id: 'type-alias-1' },
|
||||||
|
{ docType: 'const', id: 'const-1' },
|
||||||
|
{ docType: 'const', id: 'const-2' },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,25 @@
|
||||||
|
/**
|
||||||
|
* @dgService
|
||||||
|
* @description
|
||||||
|
* This file reader will pull the contents from a text file that will be used
|
||||||
|
* as the description of a package.
|
||||||
|
*
|
||||||
|
* The doc will initially have the form:
|
||||||
|
* ```
|
||||||
|
* {
|
||||||
|
* content: 'the content of the file',
|
||||||
|
* startingLine: 1
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
module.exports = function packageContentFileReader() {
|
||||||
|
return {
|
||||||
|
name: 'packageContentFileReader',
|
||||||
|
defaultPattern: /PACKAGE\.md$/,
|
||||||
|
getDocs: function(fileInfo) {
|
||||||
|
|
||||||
|
// We return a single element array because content files only contain one document
|
||||||
|
return [{docType: 'package-content', content: fileInfo.content, startingLine: 1}];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -14,7 +14,7 @@ module.exports = function createOverviewDump() {
|
||||||
modules: []
|
modules: []
|
||||||
};
|
};
|
||||||
_.forEach(docs, function(doc) {
|
_.forEach(docs, function(doc) {
|
||||||
if (doc.docType === 'module') {
|
if (doc.docType === 'package') {
|
||||||
overviewDoc.modules.push(doc);
|
overviewDoc.modules.push(doc);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{% macro githubViewHref(doc, versionInfo) -%}
|
{% macro githubViewHref(doc, versionInfo) -%}
|
||||||
https://github.com/{$ versionInfo.gitRepoInfo.owner $}/{$ versionInfo.gitRepoInfo.repo $}/tree/{$ versionInfo.currentVersion.isSnapshot and versionInfo.currentVersion.SHA or versionInfo.currentVersion.raw $}/packages/{$ doc.fileInfo.realProjectRelativePath $}#L{$ doc.startingLine + 1 $}-L{$ doc.endingLine + 1 $}
|
https://github.com/{$ versionInfo.gitRepoInfo.owner $}/{$ versionInfo.gitRepoInfo.repo $}/tree/{$ versionInfo.currentVersion.isSnapshot and versionInfo.currentVersion.SHA or versionInfo.currentVersion.raw $}/packages/{$ doc.fileInfo.realProjectRelativePath or doc.fileInfo.relativePath $}#L{$ doc.startingLine + 1 $}-L{$ doc.endingLine + 1 $}
|
||||||
{%- endmacro -%}
|
{%- endmacro -%}
|
||||||
|
|
||||||
|
|
||||||
{% macro githubEditHref(doc, versionInfo) -%}
|
{% macro githubEditHref(doc, versionInfo) -%}
|
||||||
https://github.com/{$ versionInfo.gitRepoInfo.owner $}/{$ versionInfo.gitRepoInfo.repo $}/edit/master/packages/{$ doc.fileInfo.realProjectRelativePath $}?message=docs(
|
https://github.com/{$ versionInfo.gitRepoInfo.owner $}/{$ versionInfo.gitRepoInfo.repo $}/edit/master/packages/{$ doc.fileInfo.realProjectRelativePath or doc.fileInfo.relativePath $}?message=docs(
|
||||||
{%- if doc.moduleDoc %}{$ doc.moduleDoc.id.split('/')[0] $}
|
{%- if doc.moduleDoc %}{$ doc.moduleDoc.id.split('/')[0] $}
|
||||||
{%- elseif doc.docType === 'module' %}{$ doc.id.split('/')[0] $}
|
{%- elseif doc.docType === 'package' %}{$ doc.id.split('/')[0] $}
|
||||||
{%- else %}...{%- endif -%}
|
{%- else %}...{%- endif -%}
|
||||||
)%3A%20describe%20your%20change...#L{$ doc.startingLine + 1 $}-L{$ doc.endingLine + 1 $}
|
)%3A%20describe%20your%20change...#L{$ doc.startingLine + 1 $}-L{$ doc.endingLine + 1 $}
|
||||||
{%- endmacro -%}
|
{%- endmacro -%}
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
{% extends 'base.template.html' -%}
|
|
||||||
|
|
||||||
{% block body -%}
|
|
||||||
|
|
||||||
{% include "includes/deprecation.html" %}
|
|
||||||
{% include "includes/description.html" %}
|
|
||||||
|
|
||||||
<section class="export-list">
|
|
||||||
<ul>
|
|
||||||
{% for export in doc.exports -%}
|
|
||||||
<li><a href="{$ export.path $}">{$ export.name $}</a></li>
|
|
||||||
{%- endfor %}
|
|
||||||
</ul>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{%- endblock %}
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
{% extends 'base.template.html' -%}
|
||||||
|
|
||||||
|
{% macro listItems(items, title) %}
|
||||||
|
{% if items.length %}
|
||||||
|
<section class="export-list">
|
||||||
|
<h3>{$ title $}</h3>
|
||||||
|
<table class="is-full-width list-table">
|
||||||
|
{% for item in items %}
|
||||||
|
<tr>
|
||||||
|
<td><code class="code-anchor">
|
||||||
|
<a href="{$ item.path $}">{$ item.name $}</a></code></td>
|
||||||
|
<td>{% if item.shortDescription %}{$ item.shortDescription | marked $}{% endif %}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</section>
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% block body -%}
|
||||||
|
{% include "includes/deprecation.html" %}
|
||||||
|
{$ doc.shortDescription | marked $}
|
||||||
|
{% if doc.description %}{$ doc.description | marked $}{% endif %}
|
||||||
|
|
||||||
|
{% include "includes/see-also.html" %}
|
||||||
|
|
||||||
|
<h2>Entry points</h2>
|
||||||
|
{$ listItems([doc.packageInfo.primary], 'Primary') $}
|
||||||
|
{$ listItems(doc.packageInfo.secondary, 'Secondary') $}
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Exports</h2>
|
||||||
|
{$ listItems(doc.classes, 'Classes') $}
|
||||||
|
{$ listItems(doc.decorators, 'Decorators') $}
|
||||||
|
{$ listItems(doc.functions, 'Functions') $}
|
||||||
|
{$ listItems(doc.structures, 'Structures') $}
|
||||||
|
{$ listItems(doc.directives, 'Directives') $}
|
||||||
|
{$ listItems(doc.pipes, 'Pipes') $}
|
||||||
|
{$ listItems(doc.types, 'Types') $}
|
||||||
|
{%- endblock %}
|
|
@ -0,0 +1,29 @@
|
||||||
|
Implements a domain-specific language (DSL) for defining web animation sequences for HTML elements as
|
||||||
|
multiple transformations over time.
|
||||||
|
|
||||||
|
Use this API to define how an HTML element can move, change color, grow or shrink, fade, or slide off
|
||||||
|
the page. These changes can occur simultaneously or sequentially. You can control the timing of each
|
||||||
|
of these transformations. The function calls generate the data structures and metadata that enable Angular
|
||||||
|
to integrate animations into templates and run them based on application states.
|
||||||
|
|
||||||
|
Animation definitions are linked to components through the `{@link Component.animations animations}`
|
||||||
|
property in the `@Component` metadata, typically in the component file of the HTML element to be animated.
|
||||||
|
The `trigger()` function encapsulates a named animation, with all other function calls nested within. Use
|
||||||
|
the trigger name to bind the named animation to a specific triggering element in the HTML template.
|
||||||
|
|
||||||
|
Angular animations are based on CSS web transition functionality, so anything that can be styled or
|
||||||
|
transformed in CSS can be animated the same way in Angular. Angular animations allow you to:
|
||||||
|
|
||||||
|
* Set animation timings, styles, keyframes, and transitions.
|
||||||
|
* Animate HTML elements in complex sequences and choreographies.
|
||||||
|
* Animate HTML elements as they are inserted and removed from the DOM, including responsive real-time
|
||||||
|
filtering.
|
||||||
|
* Create reusable animations.
|
||||||
|
* Animate parent and child elements.
|
||||||
|
|
||||||
|
Additional animation functionality is provided in other Angular modules for animation testing, for
|
||||||
|
route-based animations, and for programmatic animation controls that allow an end user to fast forward
|
||||||
|
and reverse an animation sequence.
|
||||||
|
|
||||||
|
@see Find out more in the [animations guide](guide/animations).
|
||||||
|
@see See what polyfills you might need in the [browser support guide](guide/browser-support).
|
Loading…
Reference in New Issue