From 4edd95a1115c8e3cb12a26641aef00c592fe7370 Mon Sep 17 00:00:00 2001 From: griest024 Date: Thu, 9 Jan 2025 16:15:35 -0500 Subject: [PATCH] feat(daffio): dynamically render doc views (#3415) --- .../src/app/docs/api/api-routing.module.ts | 4 +- apps/daffio/src/app/docs/api/api.module.ts | 9 +- .../api-package/api-package.component.html | 4 +- .../docs/api/components/doc/component.html | 7 ++ .../app/docs/api/components/doc/component.ts | 35 ++++++ .../app/docs/api/components/doc/provider.ts | 4 + .../pages/api-page/api-page.component.html | 1 - .../pages/api-page/api-page.component.spec.ts | 70 ------------ .../api/pages/api-page/api-page.component.ts | 29 ----- .../components/doc-article/component.html | 33 ++++++ .../component.scss} | 2 +- .../components/doc-article/component.spec.ts | 80 ++++++++++++++ .../docs/components/doc-article/component.ts | 35 ++++++ .../module.ts} | 8 +- .../components/doc-default/component.html | 3 + .../docs/components/doc-default/component.ts | 25 +++++ .../docs/components/doc-renderer/component.ts | 44 ++++++++ .../components/doc-renderer/component.type.ts | 7 ++ .../app/docs/components/doc-renderer/token.ts | 16 +++ .../doc-viewer/doc-viewer.component.html | 37 ------- .../doc-viewer/doc-viewer.component.spec.ts | 100 ------------------ .../doc-viewer/doc-viewer.component.ts | 59 ----------- apps/daffio/src/app/docs/docs.module.ts | 4 +- .../docs/guides/components/doc/component.html | 3 + .../docs/guides/components/doc/component.ts | 30 ++++++ .../docs/guides/components/doc/provider.ts | 4 + .../src/app/docs/guides/guides.module.ts | 4 + .../packages/components/doc/component.html | 3 + .../docs/packages/components/doc/component.ts | 32 ++++++ .../docs/packages/components/doc/provider.ts | 4 + .../src/app/docs/packages/packages.module.ts | 4 + .../pages/docs-page/docs-page.component.html | 2 +- .../docs-page/docs-page.component.spec.ts | 10 +- .../pages/docs-page/docs-page.component.ts | 4 +- 34 files changed, 396 insertions(+), 320 deletions(-) create mode 100644 apps/daffio/src/app/docs/api/components/doc/component.html create mode 100644 apps/daffio/src/app/docs/api/components/doc/component.ts create mode 100644 apps/daffio/src/app/docs/api/components/doc/provider.ts delete mode 100644 apps/daffio/src/app/docs/api/pages/api-page/api-page.component.html delete mode 100644 apps/daffio/src/app/docs/api/pages/api-page/api-page.component.spec.ts delete mode 100644 apps/daffio/src/app/docs/api/pages/api-page/api-page.component.ts create mode 100644 apps/daffio/src/app/docs/components/doc-article/component.html rename apps/daffio/src/app/docs/components/{doc-viewer/doc-viewer.component.scss => doc-article/component.scss} (98%) create mode 100644 apps/daffio/src/app/docs/components/doc-article/component.spec.ts create mode 100644 apps/daffio/src/app/docs/components/doc-article/component.ts rename apps/daffio/src/app/docs/components/{doc-viewer/doc-viewer.module.ts => doc-article/module.ts} (87%) create mode 100644 apps/daffio/src/app/docs/components/doc-default/component.html create mode 100644 apps/daffio/src/app/docs/components/doc-default/component.ts create mode 100644 apps/daffio/src/app/docs/components/doc-renderer/component.ts create mode 100644 apps/daffio/src/app/docs/components/doc-renderer/component.type.ts create mode 100644 apps/daffio/src/app/docs/components/doc-renderer/token.ts delete mode 100644 apps/daffio/src/app/docs/components/doc-viewer/doc-viewer.component.html delete mode 100644 apps/daffio/src/app/docs/components/doc-viewer/doc-viewer.component.spec.ts delete mode 100644 apps/daffio/src/app/docs/components/doc-viewer/doc-viewer.component.ts create mode 100644 apps/daffio/src/app/docs/guides/components/doc/component.html create mode 100644 apps/daffio/src/app/docs/guides/components/doc/component.ts create mode 100644 apps/daffio/src/app/docs/guides/components/doc/provider.ts create mode 100644 apps/daffio/src/app/docs/packages/components/doc/component.html create mode 100644 apps/daffio/src/app/docs/packages/components/doc/component.ts create mode 100644 apps/daffio/src/app/docs/packages/components/doc/provider.ts diff --git a/apps/daffio/src/app/docs/api/api-routing.module.ts b/apps/daffio/src/app/docs/api/api-routing.module.ts index 5594f0f805..b422d90d76 100644 --- a/apps/daffio/src/app/docs/api/api-routing.module.ts +++ b/apps/daffio/src/app/docs/api/api-routing.module.ts @@ -7,12 +7,12 @@ import { import { DaffDocKind } from '@daffodil/docs-utils'; import { DaffioApiListPageComponent } from './pages/api-list-page/api-list-page.component'; -import { DaffioApiPageComponent } from './pages/api-page/api-page.component'; import { DaffioRoute } from '../../core/router/route.type'; import { DAFFIO_DOCS_LIST_SIDEBAR_REGISTRATION } from '../containers/docs-list/sidebar.provider'; import { daffioDocsIndexResolver } from '../index/resolver'; import { DocsResolver } from '../resolvers/docs-resolver.service'; import { DAFFIO_API_NAV_LIST_SIDEBAR_REGISTRATION } from './sidebar/provider'; +import { DaffioDocsPageComponent } from '../pages/docs-page/docs-page.component'; export const apiRoutes: Routes = [ { @@ -33,7 +33,7 @@ export const apiRoutes: Routes = [ }, { path: '**', - component: DaffioApiPageComponent, + component: DaffioDocsPageComponent, resolve: { doc: DocsResolver, }, diff --git a/apps/daffio/src/app/docs/api/api.module.ts b/apps/daffio/src/app/docs/api/api.module.ts index d553114d7a..fac2eacf36 100644 --- a/apps/daffio/src/app/docs/api/api.module.ts +++ b/apps/daffio/src/app/docs/api/api.module.ts @@ -6,9 +6,8 @@ import { DaffContainerModule } from '@daffodil/design/container'; import { DaffioDocsApiRoutingModule } from './api-routing.module'; import { DaffioApiListModule } from './components/api-list/api-list.module'; +import { daffioDocsApiComponentProvider } from './components/doc/provider'; import { DaffioApiListPageComponent } from './pages/api-list-page/api-list-page.component'; -import { DaffioApiPageComponent } from './pages/api-page/api-page.component'; -import { DaffioDocViewerModule } from '../components/doc-viewer/doc-viewer.module'; @NgModule({ imports: [ @@ -16,17 +15,17 @@ import { DaffioDocViewerModule } from '../components/doc-viewer/doc-viewer.modul DaffArticleModule, DaffioDocsApiRoutingModule, DaffioApiListModule, - DaffioDocViewerModule, DaffContainerModule, ], declarations: [ DaffioApiListPageComponent, - DaffioApiPageComponent, ], exports: [ DaffioApiListPageComponent, - DaffioApiPageComponent, + ], + providers: [ + daffioDocsApiComponentProvider(), ], }) export class DaffioApiModule {} diff --git a/apps/daffio/src/app/docs/api/components/api-package/api-package.component.html b/apps/daffio/src/app/docs/api/components/api-package/api-package.component.html index e509e2313f..0e820595ae 100644 --- a/apps/daffio/src/app/docs/api/components/api-package/api-package.component.html +++ b/apps/daffio/src/app/docs/api/components/api-package/api-package.component.html @@ -5,7 +5,7 @@

{{doc.title}}

{{doc.description}}

} - + @for (package of doc.children | apiPackageFilter; track package.id) { @@ -13,6 +13,6 @@

{{doc.title}}

{{package.title}}

- + } diff --git a/apps/daffio/src/app/docs/api/components/doc/component.html b/apps/daffio/src/app/docs/api/components/doc/component.html new file mode 100644 index 0000000000..5005fbba1f --- /dev/null +++ b/apps/daffio/src/app/docs/api/components/doc/component.html @@ -0,0 +1,7 @@ + + @if (isApiPackage()) { + + } @else { +
+ } +
\ No newline at end of file diff --git a/apps/daffio/src/app/docs/api/components/doc/component.ts b/apps/daffio/src/app/docs/api/components/doc/component.ts new file mode 100644 index 0000000000..0c795470d1 --- /dev/null +++ b/apps/daffio/src/app/docs/api/components/doc/component.ts @@ -0,0 +1,35 @@ +import { + Component, + ChangeDetectionStrategy, + input, + computed, +} from '@angular/core'; +import { DaffioSafeHtmlPipe } from 'apps/daffio/src/app/core/html-sanitizer/safe.pipe'; + +import { + DaffApiDoc, + DaffDocKind, +} from '@daffodil/docs-utils'; + +import { DaffioDocArticleModule } from '../../../components/doc-article/module'; +import { DaffioDocComponent } from '../../../components/doc-renderer/component.type'; +import { DaffioApiPackageComponent } from '../api-package/api-package.component'; + +@Component({ + selector: 'daffio-api-doc', + templateUrl: './component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + standalone: true, + imports: [ + DaffioDocArticleModule, + DaffioApiPackageComponent, + DaffioSafeHtmlPipe, + ], +}) +export class DaffioDocApiComponent implements DaffioDocComponent { + static readonly kind = DaffDocKind.API; + + readonly isApiPackage = computed(() => this.doc().docType === 'package'); + + doc = input(); +} diff --git a/apps/daffio/src/app/docs/api/components/doc/provider.ts b/apps/daffio/src/app/docs/api/components/doc/provider.ts new file mode 100644 index 0000000000..38e23f356c --- /dev/null +++ b/apps/daffio/src/app/docs/api/components/doc/provider.ts @@ -0,0 +1,4 @@ +import { DaffioDocApiComponent } from './component'; +import { provideDaffioDocRendererComponents } from '../../../components/doc-renderer/token'; + +export const daffioDocsApiComponentProvider = () => provideDaffioDocRendererComponents(DaffioDocApiComponent); diff --git a/apps/daffio/src/app/docs/api/pages/api-page/api-page.component.html b/apps/daffio/src/app/docs/api/pages/api-page/api-page.component.html deleted file mode 100644 index 6bef805c56..0000000000 --- a/apps/daffio/src/app/docs/api/pages/api-page/api-page.component.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/apps/daffio/src/app/docs/api/pages/api-page/api-page.component.spec.ts b/apps/daffio/src/app/docs/api/pages/api-page/api-page.component.spec.ts deleted file mode 100644 index 3cfbcc7337..0000000000 --- a/apps/daffio/src/app/docs/api/pages/api-page/api-page.component.spec.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { - Component, - Input, -} from '@angular/core'; -import { - ComponentFixture, - TestBed, - waitForAsync, -} from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { ActivatedRoute } from '@angular/router'; -import { RouterTestingModule } from '@angular/router/testing'; -import { cold } from 'jasmine-marbles'; -import { BehaviorSubject } from 'rxjs'; - -import { DaffDoc } from '@daffodil/docs-utils'; - -import { DaffioApiPageComponent } from './api-page.component'; -import { DaffioDocsFactory } from '../../../testing/factories/docs.factory'; - -@Component({ selector: 'daffio-doc-viewer', template: '' }) -class MockDaffioDocViewerComponent { - @Input() doc: DaffDoc; -} - -describe('DaffioApiPageComponent', () => { - let component: DaffioApiPageComponent; - let fixture: ComponentFixture; - const doc: DaffDoc = new DaffioDocsFactory().create(); - const stubActivatedRoute = { - data: new BehaviorSubject({}), - }; - - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ - DaffioApiPageComponent, - MockDaffioDocViewerComponent, - ], - imports: [ - RouterTestingModule, - ], - providers: [ - { provide: ActivatedRoute, useValue: stubActivatedRoute }, - ], - }) - .compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(DaffioApiPageComponent); - component = fixture.componentInstance; - stubActivatedRoute.data.next({ doc }); - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - it('should initialize `doc$` to the resolved doc from the activated route', () => { - const expected = cold('a', { a: doc }); - expect(component.doc$).toBeObservable(expected); - }); - - it('should pass the down the observed doc to the `daffio-doc-viewer`', () => { - const docViewerComponent = fixture.debugElement.query(By.css('daffio-doc-viewer')).componentInstance; - expect(docViewerComponent.doc).toEqual(doc); - }); -}); diff --git a/apps/daffio/src/app/docs/api/pages/api-page/api-page.component.ts b/apps/daffio/src/app/docs/api/pages/api-page/api-page.component.ts deleted file mode 100644 index 046826b9da..0000000000 --- a/apps/daffio/src/app/docs/api/pages/api-page/api-page.component.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { - ChangeDetectionStrategy, - Component, - OnInit, -} from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; -import { Observable } from 'rxjs'; -import { map } from 'rxjs/operators'; - -import { DaffApiDoc } from '@daffodil/docs-utils'; - -interface ApiResolverData { - doc: DaffApiDoc; -} - -@Component({ - templateUrl: './api-page.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class DaffioApiPageComponent implements OnInit { - - doc$: Observable; - - constructor(private route: ActivatedRoute) { } - - ngOnInit() { - this.doc$ = this.route.data.pipe(map((data: ApiResolverData) => data.doc)); - } -} diff --git a/apps/daffio/src/app/docs/components/doc-article/component.html b/apps/daffio/src/app/docs/components/doc-article/component.html new file mode 100644 index 0000000000..1bb15efe8a --- /dev/null +++ b/apps/daffio/src/app/docs/components/doc-article/component.html @@ -0,0 +1,33 @@ + +
+
+ + @if (breadcrumbs.length > 0) { + + } + + + +
+ @if (toc) { + + + } +
diff --git a/apps/daffio/src/app/docs/components/doc-viewer/doc-viewer.component.scss b/apps/daffio/src/app/docs/components/doc-article/component.scss similarity index 98% rename from apps/daffio/src/app/docs/components/doc-viewer/doc-viewer.component.scss rename to apps/daffio/src/app/docs/components/doc-article/component.scss index 5f74c17492..8f971c76d6 100644 --- a/apps/daffio/src/app/docs/components/doc-viewer/doc-viewer.component.scss +++ b/apps/daffio/src/app/docs/components/doc-article/component.scss @@ -6,7 +6,7 @@ margin: 0 auto; } -.daffio-doc-viewer { +.daffio-doc-article { &__grid { padding: 24px; diff --git a/apps/daffio/src/app/docs/components/doc-article/component.spec.ts b/apps/daffio/src/app/docs/components/doc-article/component.spec.ts new file mode 100644 index 0000000000..efc9df2574 --- /dev/null +++ b/apps/daffio/src/app/docs/components/doc-article/component.spec.ts @@ -0,0 +1,80 @@ +import { Component } from '@angular/core'; +import { + ComponentFixture, + TestBed, + waitForAsync, +} from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { RouterTestingModule } from '@angular/router/testing'; +import { provideMockStore } from '@ngrx/store/testing'; + +import { DAFF_ARTICLE_COMPONENTS } from '@daffodil/design/article'; +import { + DaffApiPackageDoc, + DaffBreadcrumb, + DaffDocTableOfContents, +} from '@daffodil/docs-utils'; + +import { DaffioDocArticleComponent } from './component'; +import { DaffioApiPackageComponent } from '../../api/components/api-package/api-package.component'; +import { DaffioDocsFactory } from '../../testing/factories/docs.factory'; +import { DaffioDocsTableOfContentsModule } from '../table-of-contents/table-of-contents.module'; + +@Component({ + template: ``, +}) +class WrapperComponent { + tocValue: DaffDocTableOfContents; + breadcrumbsValue: Array; +} + +describe('DaffioDocArticleComponent', () => { + let component: DaffioDocArticleComponent; + let fixture: ComponentFixture; + let wrapper: WrapperComponent; + const docFactory = new DaffioDocsFactory(); + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [ + RouterTestingModule, + DAFF_ARTICLE_COMPONENTS, + DaffioDocsTableOfContentsModule, + DaffioApiPackageComponent, + ], + declarations: [ + WrapperComponent, + DaffioDocArticleComponent, + ], + providers: [ + provideMockStore(), + ], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(WrapperComponent); + wrapper = fixture.componentInstance; + wrapper.tocValue = []; + wrapper.breadcrumbsValue = []; + fixture.detectChanges(); + + component = fixture.debugElement.query(By.directive(DaffioDocArticleComponent)).componentInstance; + }); + + it('should create', () => { + expect(wrapper).toBeTruthy(); + }); + + it('should take toc as an input', () => { + expect(component.toc).toEqual(wrapper.tocValue); + }); + + it('should take breadcrumbs as an input', () => { + expect(component.breadcrumbs).toEqual(wrapper.breadcrumbsValue); + }); +}); diff --git a/apps/daffio/src/app/docs/components/doc-article/component.ts b/apps/daffio/src/app/docs/components/doc-article/component.ts new file mode 100644 index 0000000000..d6d9064d09 --- /dev/null +++ b/apps/daffio/src/app/docs/components/doc-article/component.ts @@ -0,0 +1,35 @@ +import { + Component, + ChangeDetectionStrategy, + Input, +} from '@angular/core'; +import { faBars } from '@fortawesome/free-solid-svg-icons'; + +import { + DaffBreadcrumb, + DaffDocTableOfContents, +} from '@daffodil/docs-utils'; + +import { DaffioSidebarService } from '../../../core/sidebar/services/sidebar.service'; +import { DAFFIO_DOCS_LIST_SIDEBAR_ID } from '../../containers/docs-list/sidebar.provider'; + +@Component({ + selector: 'daffio-doc-article', + templateUrl: './component.html', + styleUrls: ['./component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class DaffioDocArticleComponent { + faBars = faBars; + + constructor( + private sidebarService: DaffioSidebarService, + ) {} + + @Input() toc?: DaffDocTableOfContents; + @Input() breadcrumbs: Array = []; + + open() { + this.sidebarService.open(DAFFIO_DOCS_LIST_SIDEBAR_ID); + } +} diff --git a/apps/daffio/src/app/docs/components/doc-viewer/doc-viewer.module.ts b/apps/daffio/src/app/docs/components/doc-article/module.ts similarity index 87% rename from apps/daffio/src/app/docs/components/doc-viewer/doc-viewer.module.ts rename to apps/daffio/src/app/docs/components/doc-article/module.ts index a39196092c..beeddc5707 100644 --- a/apps/daffio/src/app/docs/components/doc-viewer/doc-viewer.module.ts +++ b/apps/daffio/src/app/docs/components/doc-article/module.ts @@ -12,16 +12,16 @@ import { DaffButtonModule } from '@daffodil/design/button'; import { DaffContainerModule } from '@daffodil/design/container'; import { DaffSidebarModule } from '@daffodil/design/sidebar'; -import { DaffioDocViewerComponent } from './doc-viewer.component'; +import { DaffioDocArticleComponent } from './component'; import { DaffioApiPackageComponent } from '../../api/components/api-package/api-package.component'; import { DaffioDocsTableOfContentsModule } from '../table-of-contents/table-of-contents.module'; @NgModule({ declarations: [ - DaffioDocViewerComponent, + DaffioDocArticleComponent, ], exports: [ - DaffioDocViewerComponent, + DaffioDocArticleComponent, ], imports: [ CommonModule, @@ -37,4 +37,4 @@ import { DaffioDocsTableOfContentsModule } from '../table-of-contents/table-of-c RouterLink, ], }) -export class DaffioDocViewerModule { } +export class DaffioDocArticleModule { } diff --git a/apps/daffio/src/app/docs/components/doc-default/component.html b/apps/daffio/src/app/docs/components/doc-default/component.html new file mode 100644 index 0000000000..64a3def65f --- /dev/null +++ b/apps/daffio/src/app/docs/components/doc-default/component.html @@ -0,0 +1,3 @@ + +
+
\ No newline at end of file diff --git a/apps/daffio/src/app/docs/components/doc-default/component.ts b/apps/daffio/src/app/docs/components/doc-default/component.ts new file mode 100644 index 0000000000..f46b2a18cb --- /dev/null +++ b/apps/daffio/src/app/docs/components/doc-default/component.ts @@ -0,0 +1,25 @@ +import { + Component, + ChangeDetectionStrategy, + input, +} from '@angular/core'; + +import { DaffDoc } from '@daffodil/docs-utils'; + +import { DaffioSafeHtmlPipe } from '../../../core/html-sanitizer/safe.pipe'; +import { DaffioDocArticleModule } from '../doc-article/module'; +import { DaffioDocComponent } from '../doc-renderer/component.type'; + +@Component({ + selector: 'daffio-doc-default', + templateUrl: './component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + standalone: true, + imports: [ + DaffioDocArticleModule, + DaffioSafeHtmlPipe, + ], +}) +export class DaffioDocDefaultComponent implements DaffioDocComponent { + doc = input(); +} diff --git a/apps/daffio/src/app/docs/components/doc-renderer/component.ts b/apps/daffio/src/app/docs/components/doc-renderer/component.ts new file mode 100644 index 0000000000..bd63c5e990 --- /dev/null +++ b/apps/daffio/src/app/docs/components/doc-renderer/component.ts @@ -0,0 +1,44 @@ +import { NgComponentOutlet } from '@angular/common'; +import { + Component, + Inject, + Input, + Type, +} from '@angular/core'; + +import { daffArrayToDict } from '@daffodil/core'; +import { + DaffDoc, + DaffDocKind, +} from '@daffodil/docs-utils'; + +import { DaffioDocComponent } from './component.type'; +import { + DAFFIO_DOC_RENDERER_COMPONENTS, + DaffioDocComponentInjection, +} from './token'; +import { DaffioDocDefaultComponent } from '../doc-default/component'; + +@Component({ + selector: 'daffio-doc-renderer', + standalone: true, + imports: [ + NgComponentOutlet, + ], + template: ` + + `, +}) +export class DaffioDocRendererComponent { + private readonly _map: Record> = daffArrayToDict(this.components, (c) => c.kind); + + @Input() doc: DaffDoc; + + get component(): Type> { + return this._map[this.doc.kind] || DaffioDocDefaultComponent; + } + + constructor( + @Inject(DAFFIO_DOC_RENDERER_COMPONENTS) private components: Array>, + ) {} +} diff --git a/apps/daffio/src/app/docs/components/doc-renderer/component.type.ts b/apps/daffio/src/app/docs/components/doc-renderer/component.type.ts new file mode 100644 index 0000000000..905f378fd2 --- /dev/null +++ b/apps/daffio/src/app/docs/components/doc-renderer/component.type.ts @@ -0,0 +1,7 @@ +import { InputSignal } from '@angular/core'; + +import { DaffDoc } from '@daffodil/docs-utils'; + +export interface DaffioDocComponent { + doc: InputSignal; +} diff --git a/apps/daffio/src/app/docs/components/doc-renderer/token.ts b/apps/daffio/src/app/docs/components/doc-renderer/token.ts new file mode 100644 index 0000000000..c594854137 --- /dev/null +++ b/apps/daffio/src/app/docs/components/doc-renderer/token.ts @@ -0,0 +1,16 @@ +import { Type } from '@angular/core'; + +import { createMultiInjectionToken } from '@daffodil/core'; +import { + DaffDoc, + DaffDocKind, +} from '@daffodil/docs-utils'; + +import { DaffioDocComponent } from './component.type'; + +export type DaffioDocComponentInjection = {readonly kind: DaffDocKind} & Type>; + +export const { + token: DAFFIO_DOC_RENDERER_COMPONENTS, + provider: provideDaffioDocRendererComponents, +} = createMultiInjectionToken('DAFFIO_DOC_RENDERER_COMPONENTS'); diff --git a/apps/daffio/src/app/docs/components/doc-viewer/doc-viewer.component.html b/apps/daffio/src/app/docs/components/doc-viewer/doc-viewer.component.html deleted file mode 100644 index afdc7c0fc9..0000000000 --- a/apps/daffio/src/app/docs/components/doc-viewer/doc-viewer.component.html +++ /dev/null @@ -1,37 +0,0 @@ - -
-
- @if (doc.breadcrumbs?.length > 0) { - - } - - @if (isApiPackage) { - - } @else { - - - } -
- @if (isGuideDoc) { - - - } -
diff --git a/apps/daffio/src/app/docs/components/doc-viewer/doc-viewer.component.spec.ts b/apps/daffio/src/app/docs/components/doc-viewer/doc-viewer.component.spec.ts deleted file mode 100644 index 23f5d8c86d..0000000000 --- a/apps/daffio/src/app/docs/components/doc-viewer/doc-viewer.component.spec.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { Component } from '@angular/core'; -import { - ComponentFixture, - TestBed, - waitForAsync, -} from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { RouterTestingModule } from '@angular/router/testing'; -import { provideMockStore } from '@ngrx/store/testing'; - -import { DaffArticleModule } from '@daffodil/design/article'; -import { - DaffApiDoc, - DaffApiPackageDoc, - DaffDoc, - DaffDocsApiNavList, - DaffGuideDoc, -} from '@daffodil/docs-utils'; - -import { DaffioDocViewerComponent } from './doc-viewer.component'; -import { DaffioApiPackageComponent } from '../../api/components/api-package/api-package.component'; -import { DaffioDocsFactory } from '../../testing/factories/docs.factory'; -import { DaffioDocsTableOfContentsModule } from '../table-of-contents/table-of-contents.module'; - -@Component({ - template: ``, -}) -class WrapperComponent { - doc: DaffDoc | DaffGuideDoc | DaffApiDoc | DaffApiPackageDoc; -} - -describe('DaffioDocViewerComponent', () => { - let fixture: ComponentFixture; - let wrapper: WrapperComponent; - const docFactory = new DaffioDocsFactory(); - - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - imports: [ - RouterTestingModule, - DaffArticleModule, - DaffioDocsTableOfContentsModule, - DaffioApiPackageComponent, - ], - declarations: [ - WrapperComponent, - DaffioDocViewerComponent, - ], - providers: [ - provideMockStore(), - ], - }) - .compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(WrapperComponent); - wrapper = fixture.componentInstance; - wrapper.doc = docFactory.create(); - fixture.detectChanges(); - }); - - it('should create', () => { - expect(wrapper).toBeTruthy(); - }); - - describe('when the doc is an API package doc', () => { - beforeEach(() => { - wrapper.doc = { - id: 'name1Component', - title: 'title1Component', - path: 'path1', - docType: 'package', - description: '', - children: [ - { - id: 'name1ComponentChild', - title: 'title1ComponentChild', - path: 'path1/child', - docType: 'docType1', - children: [], - }, - ], - }; - fixture.detectChanges(); - }); - - it('should render the package doc', () => { - const apiChildren: DaffioApiPackageComponent = fixture.debugElement.query(By.directive(DaffioApiPackageComponent)).componentInstance; - expect(apiChildren.doc).toEqual((wrapper.doc)); - }); - }); - - it('should render the contents of the doc as innerhtml', () => { - wrapper.doc = docFactory.create({ contents: 'Some Content' }); - fixture.detectChanges(); - const articleElement = fixture.debugElement.query(By.css('daff-article')).nativeElement; - expect(articleElement.innerHTML).toEqual(wrapper.doc.contents); - }); -}); diff --git a/apps/daffio/src/app/docs/components/doc-viewer/doc-viewer.component.ts b/apps/daffio/src/app/docs/components/doc-viewer/doc-viewer.component.ts deleted file mode 100644 index 7a4c588cf1..0000000000 --- a/apps/daffio/src/app/docs/components/doc-viewer/doc-viewer.component.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { - Component, - Input, - ChangeDetectionStrategy, -} from '@angular/core'; -import { - DomSanitizer, - SafeHtml, -} from '@angular/platform-browser'; -import { faBars } from '@fortawesome/free-solid-svg-icons'; - -import { - DaffApiDoc, - DaffApiPackageDoc, - DaffDoc, - DaffGuideDoc, -} from '@daffodil/docs-utils'; - -import { DaffioSidebarService } from '../../../core/sidebar/services/sidebar.service'; -import { DAFFIO_DOCS_LIST_SIDEBAR_ID } from '../../containers/docs-list/sidebar.provider'; - -@Component({ - selector: 'daffio-doc-viewer', - templateUrl: './doc-viewer.component.html', - styleUrls: ['./doc-viewer.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class DaffioDocViewerComponent { - faBars = faBars; - - constructor( - private sanitizer: DomSanitizer, - private sidebarService: DaffioSidebarService, - ) {} - - /** - * The doc to render - */ - @Input() doc: DaffDoc | DaffGuideDoc | DaffApiDoc | DaffApiPackageDoc; - - sanitizedContent: SafeHtml; - - get isApiPackage(): boolean { - return 'docType' in this.doc && this.doc.docType === 'package'; - } - - get isGuideDoc(): boolean { - return 'tableOfContents' in this.doc; - } - - open() { - this.sidebarService.open(DAFFIO_DOCS_LIST_SIDEBAR_ID); - } - - getInnerHtml(doc: DaffDoc | DaffGuideDoc): SafeHtml { - //It is necessary to bypass the default angular sanitization to keep id tags in the injected html. These id tags are used for fragment routing. - return this.sanitizer.bypassSecurityTrustHtml(doc.contents); - } -} diff --git a/apps/daffio/src/app/docs/docs.module.ts b/apps/daffio/src/app/docs/docs.module.ts index c342c91a15..83dadb6867 100644 --- a/apps/daffio/src/app/docs/docs.module.ts +++ b/apps/daffio/src/app/docs/docs.module.ts @@ -5,7 +5,7 @@ import { RouterModule } from '@angular/router'; import { DaffContainerModule } from '@daffodil/design/container'; import { DaffHeroModule } from '@daffodil/design/hero'; -import { DaffioDocViewerModule } from './components/doc-viewer/doc-viewer.module'; +import { DaffioDocArticleModule } from './components/doc-article/module'; import { DaffioDocsRoutingModule } from './docs-routing.module'; import { DaffioDocsIndexService } from './index/index.service'; import { DaffioDocsPageComponent } from './pages/docs-page/docs-page.component'; @@ -15,7 +15,7 @@ import { DaffioDocsPageComponent } from './pages/docs-page/docs-page.component'; CommonModule, RouterModule, - DaffioDocViewerModule, + DaffioDocArticleModule, DaffioDocsRoutingModule, DaffContainerModule, DaffHeroModule, diff --git a/apps/daffio/src/app/docs/guides/components/doc/component.html b/apps/daffio/src/app/docs/guides/components/doc/component.html new file mode 100644 index 0000000000..e7a84ae3c6 --- /dev/null +++ b/apps/daffio/src/app/docs/guides/components/doc/component.html @@ -0,0 +1,3 @@ + +
+
\ No newline at end of file diff --git a/apps/daffio/src/app/docs/guides/components/doc/component.ts b/apps/daffio/src/app/docs/guides/components/doc/component.ts new file mode 100644 index 0000000000..d9856f2f36 --- /dev/null +++ b/apps/daffio/src/app/docs/guides/components/doc/component.ts @@ -0,0 +1,30 @@ +import { + Component, + ChangeDetectionStrategy, + input, +} from '@angular/core'; +import { DaffioSafeHtmlPipe } from 'apps/daffio/src/app/core/html-sanitizer/safe.pipe'; + +import { + DaffGuideDoc, + DaffDocKind, +} from '@daffodil/docs-utils'; + +import { DaffioDocArticleModule } from '../../../components/doc-article/module'; +import { DaffioDocComponent } from '../../../components/doc-renderer/component.type'; + +@Component({ + selector: 'daffio-api-doc', + templateUrl: './component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + standalone: true, + imports: [ + DaffioDocArticleModule, + DaffioSafeHtmlPipe, + ], +}) +export class DaffioDocGuideComponent implements DaffioDocComponent { + static readonly kind = DaffDocKind.GUIDE; + + doc = input(); +} diff --git a/apps/daffio/src/app/docs/guides/components/doc/provider.ts b/apps/daffio/src/app/docs/guides/components/doc/provider.ts new file mode 100644 index 0000000000..f0564f2e71 --- /dev/null +++ b/apps/daffio/src/app/docs/guides/components/doc/provider.ts @@ -0,0 +1,4 @@ +import { DaffioDocGuideComponent } from './component'; +import { provideDaffioDocRendererComponents } from '../../../components/doc-renderer/token'; + +export const daffioDocsGuideComponentProvider = () => provideDaffioDocRendererComponents(DaffioDocGuideComponent); diff --git a/apps/daffio/src/app/docs/guides/guides.module.ts b/apps/daffio/src/app/docs/guides/guides.module.ts index 708adae50d..b85c2d1f07 100644 --- a/apps/daffio/src/app/docs/guides/guides.module.ts +++ b/apps/daffio/src/app/docs/guides/guides.module.ts @@ -1,10 +1,14 @@ import { NgModule } from '@angular/core'; +import { daffioDocsGuideComponentProvider } from './components/doc/provider'; import { DaffioGuidesRoutingModule } from './guides-routing.module'; @NgModule({ imports: [ DaffioGuidesRoutingModule, ], + providers: [ + daffioDocsGuideComponentProvider(), + ], }) export class DaffioGuidesModule {} diff --git a/apps/daffio/src/app/docs/packages/components/doc/component.html b/apps/daffio/src/app/docs/packages/components/doc/component.html new file mode 100644 index 0000000000..e7a84ae3c6 --- /dev/null +++ b/apps/daffio/src/app/docs/packages/components/doc/component.html @@ -0,0 +1,3 @@ + +
+
\ No newline at end of file diff --git a/apps/daffio/src/app/docs/packages/components/doc/component.ts b/apps/daffio/src/app/docs/packages/components/doc/component.ts new file mode 100644 index 0000000000..e8caba88d3 --- /dev/null +++ b/apps/daffio/src/app/docs/packages/components/doc/component.ts @@ -0,0 +1,32 @@ +import { + Component, + ChangeDetectionStrategy, + input, + computed, +} from '@angular/core'; +import { DomSanitizer } from '@angular/platform-browser'; +import { DaffioSafeHtmlPipe } from 'apps/daffio/src/app/core/html-sanitizer/safe.pipe'; + +import { + DaffPackageGuideDoc, + DaffDocKind, +} from '@daffodil/docs-utils'; + +import { DaffioDocArticleModule } from '../../../components/doc-article/module'; +import { DaffioDocComponent } from '../../../components/doc-renderer/component.type'; + +@Component({ + selector: 'daffio-api-doc', + templateUrl: './component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + standalone: true, + imports: [ + DaffioDocArticleModule, + DaffioSafeHtmlPipe, + ], +}) +export class DaffioDocPackageComponent implements DaffioDocComponent { + static readonly kind = DaffDocKind.PACKAGE; + + doc = input(); +} diff --git a/apps/daffio/src/app/docs/packages/components/doc/provider.ts b/apps/daffio/src/app/docs/packages/components/doc/provider.ts new file mode 100644 index 0000000000..459475f61a --- /dev/null +++ b/apps/daffio/src/app/docs/packages/components/doc/provider.ts @@ -0,0 +1,4 @@ +import { DaffioDocPackageComponent } from './component'; +import { provideDaffioDocRendererComponents } from '../../../components/doc-renderer/token'; + +export const daffioDocsPackageComponentProvider = () => provideDaffioDocRendererComponents(DaffioDocPackageComponent); diff --git a/apps/daffio/src/app/docs/packages/packages.module.ts b/apps/daffio/src/app/docs/packages/packages.module.ts index dea9cdc95a..5b494e483c 100644 --- a/apps/daffio/src/app/docs/packages/packages.module.ts +++ b/apps/daffio/src/app/docs/packages/packages.module.ts @@ -5,6 +5,7 @@ import { RouterModule } from '@angular/router'; import { DaffContainerModule } from '@daffodil/design/container'; import { DaffHeroModule } from '@daffodil/design/hero'; +import { daffioDocsPackageComponentProvider } from './components/doc/provider'; import { DaffioDocsPackageCardsContainerModule } from './containers/package-cards/package-cards.module'; import { DaffioPackagesRoutingModule } from './packages-routing.module'; import { DaffioPackagesOverviewPageComponent } from './pages/packages-overview/packages-overview.component'; @@ -25,5 +26,8 @@ import { DaffioPackagesOverviewPageComponent } from './pages/packages-overview/p exports: [ DaffioPackagesOverviewPageComponent, ], + providers: [ + daffioDocsPackageComponentProvider(), + ], }) export class DaffioPackagesModule {} diff --git a/apps/daffio/src/app/docs/pages/docs-page/docs-page.component.html b/apps/daffio/src/app/docs/pages/docs-page/docs-page.component.html index b98d70acd5..0a48730666 100644 --- a/apps/daffio/src/app/docs/pages/docs-page/docs-page.component.html +++ b/apps/daffio/src/app/docs/pages/docs-page/docs-page.component.html @@ -1 +1 @@ - + diff --git a/apps/daffio/src/app/docs/pages/docs-page/docs-page.component.spec.ts b/apps/daffio/src/app/docs/pages/docs-page/docs-page.component.spec.ts index da35e9b6b2..26b822193e 100644 --- a/apps/daffio/src/app/docs/pages/docs-page/docs-page.component.spec.ts +++ b/apps/daffio/src/app/docs/pages/docs-page/docs-page.component.spec.ts @@ -19,8 +19,8 @@ import { DaffDoc } from '@daffodil/docs-utils'; import { DaffioDocsPageComponent } from './docs-page.component'; import { DaffioDocsFactory } from '../../../docs/testing/factories/docs.factory'; -@Component({ selector: 'daffio-doc-viewer', template: '' }) -class MockDaffioDocViewerComponent { +@Component({ selector: 'daffio-doc-renderer', template: '' }) +class MockDaffioDocRendererComponent { @Input() doc: DaffDoc; } @@ -35,7 +35,7 @@ describe('DaffioDocsPageComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [ - MockDaffioDocViewerComponent, + MockDaffioDocRendererComponent, ], imports: [ DaffioDocsPageComponent, @@ -65,8 +65,8 @@ describe('DaffioDocsPageComponent', () => { expect(component.doc$).toBeObservable(expected); }); - it('should pass the down the observed doc to the `daffio-doc-viewer`', () => { - const docViewerComponent = fixture.debugElement.query(By.css('daffio-doc-viewer')).componentInstance; + it('should pass the down the observed doc to the `daffio-doc-article`', () => { + const docViewerComponent: MockDaffioDocRendererComponent = fixture.debugElement.query(By.css('daffio-doc-renderer')).componentInstance; expect(docViewerComponent.doc).toEqual(doc); }); }); diff --git a/apps/daffio/src/app/docs/pages/docs-page/docs-page.component.ts b/apps/daffio/src/app/docs/pages/docs-page/docs-page.component.ts index 39c1cce5e1..5f686e10a9 100644 --- a/apps/daffio/src/app/docs/pages/docs-page/docs-page.component.ts +++ b/apps/daffio/src/app/docs/pages/docs-page/docs-page.component.ts @@ -13,7 +13,7 @@ import { map } from 'rxjs/operators'; import { DaffDoc } from '@daffodil/docs-utils'; -import { DaffioDocViewerModule } from '../../components/doc-viewer/doc-viewer.module'; +import { DaffioDocRendererComponent } from '../../components/doc-renderer/component'; @Component({ selector: 'daffio-docs-page', @@ -23,7 +23,7 @@ import { DaffioDocViewerModule } from '../../components/doc-viewer/doc-viewer.mo imports: [ AsyncPipe, RouterModule, - DaffioDocViewerModule, + DaffioDocRendererComponent, ], }) export class DaffioDocsPageComponent implements OnInit {