Skip to content

Commit

Permalink
feat(core): support automatic generate api docs #OSP-230 (#294)
Browse files Browse the repository at this point in the history
  • Loading branch information
why520crazy committed Dec 16, 2021
1 parent 6aa9612 commit 5b428a0
Show file tree
Hide file tree
Showing 45 changed files with 943 additions and 180 deletions.
1 change: 1 addition & 0 deletions .docgenirc.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ module.exports = {
rootDir: './packages/a-lib',
include: ['common'],
exclude: '',
apiMode: 'compatible',
categories: [
{
id: 'general',
Expand Down
13 changes: 13 additions & 0 deletions packages/a-lib/button/button.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { Component, OnInit, HostBinding, Input, ElementRef } from '@angular/core';

/**
* Button 2
*/
@Component({
selector: 'alib-button,[alibButton]',
template: '<ng-content></ng-content>'
Expand All @@ -8,6 +11,11 @@ export class AlibButtonComponent implements OnInit {
@HostBinding(`class.dg-btn`) isBtn = true;

private type: string;

/**
* Button Type: `'primary' | 'secondary' | 'danger'`
* @default primary
*/
@Input() set alibButton(value: string) {
if (this.type) {
this.elementRef.nativeElement.classList.remove(`dg-btn-${this.type}`);
Expand All @@ -16,6 +24,11 @@ export class AlibButtonComponent implements OnInit {
this.elementRef.nativeElement.classList.add(`dg-btn-${this.type}`);
}

/**
* Button Size
*/
@Input() alibSize: 'xs' | 'sm' | 'md' | 'lg' = 'xs';

constructor(private elementRef: ElementRef<HTMLElement>) {}

ngOnInit(): void {}
Expand Down
File renamed without changes.
24 changes: 21 additions & 3 deletions packages/a-lib/foo/foo.component.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,30 @@
import { Component, OnInit } from '@angular/core';
import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core';

/**
* Foo Component
*/
@Component({
selector: 'alib-foo',
template: `<ng-content></ng-content>
template: `
<ng-content></ng-content>
`
})
export class AlibFooComponent implements OnInit {
/**
* Type is foo
* @type string
*/
@Input() alibType: 'primary' | 'secondary';

/**
* Close event when foo close
* @type string
*/
@Output() alibClose = new EventEmitter<string>();

constructor() {}

ngOnInit(): void {}
ngOnInit(): void {
this.alibClose.emit('hello');
}
}
7 changes: 6 additions & 1 deletion packages/a-lib/layout/layout.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, OnInit, HostBinding } from '@angular/core';
import { Component, OnInit, HostBinding, Input } from '@angular/core';

@Component({
selector: 'alib-layout',
Expand All @@ -9,6 +9,11 @@ import { Component, OnInit, HostBinding } from '@angular/core';
export class AlibLayoutComponent implements OnInit {
@HostBinding(`class.alib-layout`) isLayout = true;

/**
* Direction `vertical`
*/
@Input() thyDirection: 'vertical' | 'horizontal';

constructor() {}

ngOnInit(): void {}
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/build.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe('#cli', () => {
config: {
...config,
skipSite: true
}
} as unknown
});
await docgeni.run();
const expectConfig = { ...DEFAULT_CONFIG, ...config };
Expand Down
66 changes: 61 additions & 5 deletions packages/core/src/builders/library-builder.spec.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { toolkit } from '@docgeni/toolkit';
import { DocgeniContext } from '../docgeni.interface';
import { HostWatchEvent, HostWatchEventType, normalize, resolve } from '../fs';
import { createTestDocgeniContext, DEFAULT_TEST_ROOT_PATH, FixtureResult, loadFixture } from '../testing';
import { HostWatchEventType, normalize, resolve } from '../fs';
import { createTestDocgeniContext, DEFAULT_TEST_ROOT_PATH, FixtureResult, loadFixture, NgParserSpectator } from '../testing';
import { LibraryBuilderImpl } from './library-builder';
import { normalizeLibConfig } from './normalize';
import * as systemPath from 'path';
import { ChannelItem, NavigationItem } from '../interfaces';
import { ASSETS_API_DOCS_RELATIVE_PATH, ASSETS_EXAMPLES_HIGHLIGHTED_RELATIVE_PATH, ASSETS_OVERVIEWS_RELATIVE_PATH } from '../constants';
import { Observable, of } from 'rxjs';
import { NavigationItem } from '../interfaces';
import { of } from 'rxjs';
import { LibraryBuilder, LibraryComponent } from '../types';
import { DefaultNgParserHost, NgParserHost, ts, NgDocParser, DefaultNgParserHostOptions, NgDocParserOptions } from '@docgeni/ngdoc';

class LibraryBuilderSpectator {
components: LibraryComponent[];
Expand Down Expand Up @@ -294,6 +294,62 @@ describe('#library-builder', () => {
});
});

it('should create ngDocParser with automatic api mode', async () => {
library.apiMode = 'automatic';
const ngParserSpectator = new NgParserSpectator();

const tsconfig = resolve(libDirPath, 'tsconfig.lib.json');
context.host.writeFile(tsconfig, '{includes: []}');
const libraryBuilder = new LibraryBuilderImpl(context, library);
expect(libraryBuilder.getNgDocParser()).toBeFalsy();
ngParserSpectator.notHaveBeenCalled();
await libraryBuilder.initialize();
ngParserSpectator.toHaveBeenCalled({
tsConfigPath: tsconfig,
rootDir: libDirPath,
watch: true
});
expect(libraryBuilder.getNgDocParser()).toEqual(ngParserSpectator.mockNgParser);
});

it('should create ngDocParser with compatible api mode', async () => {
library.apiMode = 'compatible';
const ngParserSpectator = new NgParserSpectator();

const tsconfig = resolve(libDirPath, 'tsconfig.lib.json');
context.host.writeFile(tsconfig, '{includes: []}');
const libraryBuilder = new LibraryBuilderImpl(context, library);
expect(libraryBuilder.getNgDocParser()).toBeFalsy();
ngParserSpectator.notHaveBeenCalled();
await libraryBuilder.initialize();
ngParserSpectator.toHaveBeenCalled({
tsConfigPath: tsconfig,
rootDir: libDirPath,
watch: true
});
expect(libraryBuilder.getNgDocParser()).toEqual(ngParserSpectator.mockNgParser);
});

it('should rebuild component when watch api docs', async () => {
library.apiMode = 'compatible';
const ngParserSpectator = new NgParserSpectator();

const tsconfig = resolve(libDirPath, 'tsconfig.lib.json');
context.host.writeFile(tsconfig, '{includes: []}');
const libraryBuilder = new LibraryBuilderImpl(context, library);
expect(libraryBuilder.getNgDocParser()).toBeFalsy();
ngParserSpectator.notHaveBeenCalled();
await libraryBuilder.initialize();
const compileSpy = spyOn(context, 'compile');
expect(compileSpy).not.toHaveBeenCalled();
ngParserSpectator.fakeFileChange(resolve(libDirPath, './button/button.component.ts'));
expect(compileSpy).toHaveBeenCalledWith({
libraryBuilder: libraryBuilder,
libraryComponents: [libraryBuilder.components.get(resolve(libDirPath, 'button'))],
changes: []
});
});

describe('watch', () => {
it('should watch components', async () => {
const libraryBuilder = new LibraryBuilderImpl(context, library);
Expand Down
43 changes: 36 additions & 7 deletions packages/core/src/builders/library-builder.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
import { DocgeniContext } from '../docgeni.interface';
import { CategoryItem, ChannelItem, ComponentDocItem, ExampleSourceFile, Library, LiveExample, NavigationItem } from '../interfaces';
import { toolkit } from '@docgeni/toolkit';
import {
ASSETS_API_DOCS_RELATIVE_PATH,
ASSETS_EXAMPLES_HIGHLIGHTED_RELATIVE_PATH,
ASSETS_OVERVIEWS_RELATIVE_PATH,
SITE_ASSETS_RELATIVE_PATH
} from '../constants';
import { ascendingSortByOrder, getItemLocaleProperty } from '../utils';

import { AsyncSeriesHook, SyncHook } from 'tapable';
import { LibraryComponentImpl } from './library-component';
import { HostWatchEventType, relative, resolve } from '../fs';
import { EmitFile, EmitFiles, LibraryBuilder, LibraryComponent } from '../types';
import { FileEmitter } from './emitter';
import { ts, NgDocParser, DefaultNgParserHost } from '@docgeni/ngdoc';

export class LibraryBuilderImpl extends FileEmitter implements LibraryBuilder {
private absLibPath: string;
private localeCategoriesMap: Record<string, CategoryItem[]> = {};
private componentsMap = new Map<string, LibraryComponent>();
private ngDocParser: NgDocParser;

constructor(private docgeni: DocgeniContext, public lib: Library) {
super();
Expand All @@ -29,6 +24,10 @@ export class LibraryBuilderImpl extends FileEmitter implements LibraryBuilder {
return this.componentsMap;
}

public getNgDocParser() {
return this.ngDocParser;
}

public async initialize(): Promise<void> {
this.buildLocaleCategoriesMap(this.lib.categories);

Expand Down Expand Up @@ -56,6 +55,36 @@ export class LibraryBuilderImpl extends FileEmitter implements LibraryBuilder {
components.push(component);
this.componentsMap.set(absComponentPath, component);
});

this.watch();
await this.initializeNgDocParser();
}

private async initializeNgDocParser() {
if (this.lib.apiMode !== 'manual') {
const tsConfigPath = resolve(this.docgeni.paths.cwd, resolve(this.lib.rootDir, 'tsconfig.lib.json'));
if (await this.docgeni.host.exists(tsConfigPath)) {
const parserHost = DefaultNgParserHost.create({
tsConfigPath: tsConfigPath,
watch: this.docgeni.watch,
rootDir: this.docgeni.paths.getAbsPath(this.lib.rootDir),
watcher: (event, filename) => {
const changes: LibraryComponent[] = [];
for (const [key, component] of this.components) {
if (filename.includes(key)) {
changes.push(component);
}
}
this.docgeni.compile({
libraryBuilder: this,
libraryComponents: changes,
changes: []
});
}
});
this.ngDocParser = this.lib.ngDocParser = NgDocParser.create({ ngParserHost: parserHost });
}
}
}

public async build(components: LibraryComponent[] = Array.from(this.componentsMap.values())): Promise<void> {
Expand Down

0 comments on commit 5b428a0

Please sign in to comment.