diff --git a/angular.json b/angular.json index f5e06acf..ca714158 100644 --- a/angular.json +++ b/angular.json @@ -195,6 +195,7 @@ "tsConfig": "docs/tsconfig.app.json", "polyfills": "docs/polyfills.ts", "assets": [ + "docs/articles", "docs/assets", "docs/404.html", "docs/favicon.png", diff --git a/docs/app/@theme/components/page-toc/page-toc.component.ts b/docs/app/@theme/components/page-toc/page-toc.component.ts index f269d8d0..c2d833bd 100644 --- a/docs/app/@theme/components/page-toc/page-toc.component.ts +++ b/docs/app/@theme/components/page-toc/page-toc.component.ts @@ -13,7 +13,7 @@ import { } from '@angular/core'; import { takeWhile, map } from 'rxjs/operators'; import { ActivatedRoute } from '@angular/router'; -import { of as observableOf, combineLatest } from 'rxjs'; +import { combineLatest, Observable } from 'rxjs'; @Component({ selector: 'ngx-page-toc', @@ -35,11 +35,11 @@ export class NgxPageTocComponent implements OnDestroy { items: any[]; @Input() - set toc(value) { - combineLatest( - observableOf(value || []), + set toc(value: Observable) { + combineLatest([ + value, this.activatedRoute.fragment, - ) + ]) .pipe( takeWhile(() => this.alive), map(([toc, fragment]) => { diff --git a/docs/app/@theme/services/article.service.ts b/docs/app/@theme/services/article.service.ts new file mode 100644 index 00000000..49b24fca --- /dev/null +++ b/docs/app/@theme/services/article.service.ts @@ -0,0 +1,13 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable } from 'rxjs'; + +@Injectable() +export class NgxArticleService { + + constructor(private http: HttpClient) { } + + getArticle(source: string): Observable { + return this.http.get(`articles/${source}`, { responseType: 'text' }); + } +} diff --git a/docs/app/@theme/services/index.ts b/docs/app/@theme/services/index.ts index 98ad2799..fb2685b5 100644 --- a/docs/app/@theme/services/index.ts +++ b/docs/app/@theme/services/index.ts @@ -18,6 +18,7 @@ import { NgxCodeLoaderService } from './code-loader.service'; import { NgxStylesService } from './styles.service'; import { NgxIframeCommunicatorService } from './iframe-communicator.service'; import { NgxVisibilityService } from './visibility.service'; +import { NgxArticleService } from './article.service'; export const ngxLandingServices = [ @@ -35,4 +36,5 @@ export const ngxLandingServices = [ NgxStylesService, NgxIframeCommunicatorService, NgxVisibilityService, + NgxArticleService, ]; diff --git a/docs/app/@theme/services/structure.service.ts b/docs/app/@theme/services/structure.service.ts index d32f3fa2..0746d1c7 100644 --- a/docs/app/@theme/services/structure.service.ts +++ b/docs/app/@theme/services/structure.service.ts @@ -5,10 +5,13 @@ */ import { Inject, Injectable } from '@angular/core'; +import { map } from 'rxjs/operators'; +import { combineLatest, Observable, of } from 'rxjs'; import { NgxTabbedService } from './tabbed.service'; import { NgxTextService } from './text.service'; import { DOCS, STRUCTURE } from '../../app.options'; +import { NgxArticleService } from './article.service'; @Injectable() export class NgxStructureService { @@ -17,6 +20,7 @@ export class NgxStructureService { constructor(private textService: NgxTextService, private tabbedService: NgxTabbedService, + private articleService: NgxArticleService, @Inject(STRUCTURE) structure, @Inject(DOCS) docs) { this.prepared = this.prepareStructure(structure, docs); @@ -56,8 +60,9 @@ export class NgxStructureService { } if (item.block === 'markdown') { - item.children = this.textService.mdToSectionsHTML( - require(`raw-loader!../../../articles/${item.source}`).default); + item.sections = this.articleService.getArticle(item.source).pipe( + map((article) => this.textService.mdToSectionsHTML(article)), + ); } if (item.children) { @@ -113,39 +118,43 @@ export class NgxStructureService { }; } - protected prepareToc(item: any) { - return item.children.reduce((acc: any[], child: any) => { + protected prepareToc(item: any): Observable { + const tocList = item.children.reduce((acc: Observable[], child: any) => { if (child.block === 'markdown') { - return acc.concat(this.getTocForMd(child)); - } else if (child.block === 'tabbed') { - return acc.concat(this.getTocForTabbed(child)); - } else if (child.block === 'component') { - acc.push(this.getTocForComponent(child)); + return [...acc, this.getTocForMd(child)]; + } + if (child.block === 'tabbed') { + return [...acc, this.getTocForTabbed(child)]; + } + if (child.block === 'component') { + return [...acc, this.getTocForComponent(child)]; } return acc; }, []); + + return combineLatest([...tocList]).pipe(map((toc) => [].concat(...toc))); } - protected getTocForMd(block: any) { - return block.children.map((section: any) => ({ - title: section.title, - fragment: section.fragment, - } - )); + protected getTocForMd(block: any): Observable { + return (block.sections as Observable).pipe( + map((item) => item.map((val) => ({ + title: val.title, + fragment: val.fragment, + }))), + ); } - protected getTocForComponent(block: any) { - return { + protected getTocForComponent(block: any): Observable { + return of([{ title: block.source.name, fragment: block.source.slag, - }; + }]); } - protected getTocForTabbed(block: any) { - return block.children.map((component: any) => ({ - title: component.name, - fragment: this.textService.createSlag(component.name), - } - )); + protected getTocForTabbed(block: any): Observable { + return of(block.children.map((component: any) => ({ + title: component.name, + fragment: this.textService.createSlag(component.name), + }))); } } diff --git a/docs/app/blocks/components/md-block/md-block.component.ts b/docs/app/blocks/components/md-block/md-block.component.ts index c02d0686..f38e81e0 100644 --- a/docs/app/blocks/components/md-block/md-block.component.ts +++ b/docs/app/blocks/components/md-block/md-block.component.ts @@ -5,19 +5,34 @@ */ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; @Component({ selector: 'ngx-md-block', template: ` - + -
+
`, changeDetection: ChangeDetectionStrategy.OnPush, }) export class NgxMdBLockComponent { + @Input() content: MdChildren[] = []; - @Input() source: string; + constructor(private readonly domSanitizer: DomSanitizer) { + } + + // TODO: create NbDOMPurifyPipe + getTemplate(content: string): SafeHtml { + return this.domSanitizer.bypassSecurityTrustHtml(content); + } +} + +interface MdChildren { + fragment: string; + html: string; + source: string; + title: string; } diff --git a/docs/app/pages/docs/page/ngx-admin-landing-page.component.html b/docs/app/pages/docs/page/ngx-admin-landing-page.component.html index dc5e37ba..b3c7d8a9 100644 --- a/docs/app/pages/docs/page/ngx-admin-landing-page.component.html +++ b/docs/app/pages/docs/page/ngx-admin-landing-page.component.html @@ -11,7 +11,7 @@ - +