Skip to content

Commit

Permalink
fix(template): refresh page with fragment auto scrollToAnchor #OSP-190 (
Browse files Browse the repository at this point in the history
  • Loading branch information
why520crazy committed Sep 24, 2021
1 parent 84cb57e commit 6ebd0e5
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 53 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ jobs:
- run: yarn lint
- run: yarn test-coverage
- run: yarn test-template --no-watch --no-progress --browsers=ChromeHeadlessCI
# - run: yarn report-coverage
- run: yarn report-coverage
2 changes: 1 addition & 1 deletion docs/configuration/front-matter.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ toc: menu
- 类型:`content | menu | hidden | false`
- 默认:`content`

文档目录显示方式,值为`content`表示在内容区域右侧显示,值为`menu`时会将当前路由的目录展示在左侧菜单中,其他值表示不显示目录,默认为[全局配置](/configuration/global#toc)
文档目录显示方式,值为`content`表示在内容区域右侧显示,值为`menu`时会将当前路由的目录展示在左侧菜单中,其他值表示不显示目录,默认为 [全局配置](/configuration/global#toc)

## label <label>1.1.0+</label>
- 类型:`string`
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/compilation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,11 @@ export class DocgeniCompilationImpl implements DocgeniCompilation {
const file = this.preparedEmitFiles[path];
await this.docgeni.host.writeFile(path, toolkit.utils.isString(file) ? file : file.content);
}
await this.seal();
this.hooks.finish.call();
} catch (error) {
this.docgeni.logger.error(error);
} finally {
await this.seal();
this.hooks.finish.call();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<hr class="dg-divider dg-mt-4" />
<dg-doc-meta [docItem]="docItem"></dg-doc-meta>
</div>
<dg-toc #toc *ngIf="docItem.toc === 'content'"></dg-toc>
<dg-toc *ngIf="hasContentToc"></dg-toc>
</div>
</ng-template>
<dg-footer></dg-footer>
Expand Down
15 changes: 8 additions & 7 deletions packages/template/src/pages/doc-viewer/doc-viewer.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Component, HostBinding, NgModuleFactory, OnDestroy, OnInit, Type, ViewChild } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Observable, Subject } from 'rxjs';
import { Observable, Subject, combineLatest } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { NavigationItem } from '../../interfaces/public-api';
import { PageTitleService } from '../../services/page-title.service';
Expand All @@ -20,8 +20,6 @@ export class DocViewerComponent implements OnInit, OnDestroy {

@HostBinding(`class.dg-doc-viewer--toc`) hasContentToc = false;

// @HostBinding(`class.dg-scroll-container`) isScrollContainer = this.global.config.mode === 'lite';

/** Component type for the current example. */
exampleComponentType: Type<any> | null = null;

Expand All @@ -45,7 +43,8 @@ export class DocViewerComponent implements OnInit, OnDestroy {
private route: ActivatedRoute,
private router: Router,
private navigationService: NavigationService,
private pageTitle: PageTitleService
private pageTitle: PageTitleService,
private tocService: TocService
) {}

ngOnInit(): void {
Expand Down Expand Up @@ -73,9 +72,11 @@ export class DocViewerComponent implements OnInit, OnDestroy {
}
});

this.navigationService.docItem$.pipe(takeUntil(this.destroyed)).subscribe(docItem => {
this.hasContentToc = docItem.toc === 'content';
});
combineLatest([this.navigationService.docItem$, this.tocService.links$])
.pipe(takeUntil(this.destroyed))
.subscribe(result => {
this.hasContentToc = result[0].toc === 'content' && result[1].length > 0;
});
}

close() {
Expand Down
35 changes: 26 additions & 9 deletions packages/template/src/services/toc.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { DOCUMENT } from '@angular/common';
import { DOCUMENT, ViewportScroller } from '@angular/common';
import { Inject, Injectable } from '@angular/core';
import { fromEvent, Observable, Subject } from 'rxjs';
import { fromEvent, Observable, BehaviorSubject, Subject } from 'rxjs';
import { debounceTime, takeUntil } from 'rxjs/operators';
import { GlobalContext } from './global-context';

Expand Down Expand Up @@ -32,29 +32,32 @@ let OFFSET = 0;
providedIn: 'root'
})
export class TocService {
private linksSubject$ = new Subject<TocLink[]>();
private activeLinkSubject$ = new Subject<TocLink>();
private linksSubject$ = new BehaviorSubject<TocLink[]>([]);
private activeLinkSubject$ = new BehaviorSubject<TocLink>(null);
private destroyed$ = new Subject<TocLink[]>();
private scrollContainer: HTMLElement & Window;
public links: TocLink[];
public highestLevel: number;
public get links$(): Observable<TocLink[]> {
return this.linksSubject$.asObservable();
}

public get links() {
return this.linksSubject$.value;
}

public get activeLink$(): Observable<TocLink> {
return this.activeLinkSubject$.asObservable();
}

constructor(@Inject(DOCUMENT) private document: any, global: GlobalContext) {
constructor(@Inject(DOCUMENT) private document: any, global: GlobalContext, private viewportScroller: ViewportScroller) {
if (global.config.mode === 'lite') {
OFFSET = 0;
}
this.viewportScroller.setOffset([0, OFFSET]);
}

reset() {
this.links = [];
this.linksSubject$.next(this.links);
this.linksSubject$.next([]);
this.activeLinkSubject$.next(null);
this.highestLevel = 0;
this.destroyed$.next();
Expand All @@ -80,7 +83,6 @@ export class TocService {
});
this.highestLevel = this.highestLevel && headerLevel > this.highestLevel ? this.highestLevel : headerLevel;
});
this.links = links;
this.linksSubject$.next(links);
this.initializeScrollContainer(scrollContainer);
}
Expand Down Expand Up @@ -119,6 +121,21 @@ export class TocService {
this.activeLinkSubject$.next(activeItem || null);
}

scrollToAnchor(urlFragment: string) {
if (this.scrollContainer) {
if (this.scrollContainer === this.document.window) {
this.viewportScroller.scrollToAnchor(urlFragment);
} else {
const link = this.links.find(link => {
return link.name === urlFragment;
});
if (link) {
this.scrollContainer.scrollTop = link.element.offsetTop - 10;
}
}
}
}

private getScrollOffset(): number | void {
if (this.scrollContainer) {
if (typeof this.scrollContainer.scrollTop !== 'undefined') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,9 @@ import {
} from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { ComponentPortal } from '@angular/cdk/portal';
import { DomSanitizer } from '@angular/platform-browser';
import { ExampleViewerComponent } from '../example-viewer/example-viewer.component';
import { Subscription } from 'rxjs';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { take } from 'rxjs/operators';
import { DomPortalOutlet } from '../../services/dom-portal-outlet';
import { BuiltInComponentDef } from '../../built-in/built-in-component';
import { getBuiltInComponents } from '../../built-in/built-in-components';
import { ContentRenderer } from '../content-renderer ';
import { TocService } from '../../services/toc.service';
Expand Down
2 changes: 1 addition & 1 deletion packages/template/src/shared/toc/toc.component.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div class="dg-toc-container">
<ul [attr.aria-label]="'Table of Contents'">
<li
*ngFor="let link of tocService.links; let i = index"
*ngFor="let link of tocService.links$ | async; let i = index"
class="dg-level-{{ link.type }}"
[attr.data-level]="link.level - tocService.highestLevel + 1"
>
Expand Down
42 changes: 15 additions & 27 deletions packages/template/src/shared/toc/toc.component.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { AfterViewInit, Component, Inject, Input, OnDestroy, OnInit, HostBinding } from '@angular/core';
import { DOCUMENT, LocationStrategy, ViewportScroller } from '@angular/common';
import { Component, Input, OnDestroy, OnInit, HostBinding } from '@angular/core';
import { LocationStrategy, ViewportScroller } from '@angular/common';
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
import { Subject, fromEvent } from 'rxjs';
import { debounceTime, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { GlobalContext } from '../../services/global-context';
import { TocLink, TocService } from '../../services/toc.service';

Expand All @@ -12,20 +12,18 @@ let OFFSET = 60;
selector: 'dg-toc',
templateUrl: './toc.component.html'
})
export class TableOfContentsComponent implements OnInit, AfterViewInit, OnDestroy {
export class TableOfContentsComponent implements OnInit, OnDestroy {
@HostBinding(`class.dg-toc`) isToc = true;

@Input() container: string = '.dg-scroll-container';

links: TocLink[] = [];

activeLink: TocLink = null;

rootUrl = this.locationStrategy.path(false);

public highestLevel: number;

@HostBinding('class.dg-d-none')
private hideToc = true;
@HostBinding('class.dg-d-none') hideToc = true;

private destroyed = new Subject();

Expand All @@ -34,8 +32,6 @@ export class TableOfContentsComponent implements OnInit, AfterViewInit, OnDestro
constructor(
private router: Router,
private route: ActivatedRoute,
@Inject(DOCUMENT) private document: any,
private viewportScroller: ViewportScroller,
global: GlobalContext,
private locationStrategy: LocationStrategy,
public tocService: TocService
Expand All @@ -52,41 +48,33 @@ export class TableOfContentsComponent implements OnInit, AfterViewInit, OnDestro
}
});

this.viewportScroller.setOffset([0, OFFSET]);

this.route.fragment.pipe(takeUntil(this.destroyed)).subscribe(fragment => {
this.urlFragment = fragment;
this.viewportScroller.scrollToAnchor(this.urlFragment);
this.tocService.scrollToAnchor(this.urlFragment);
});

this.tocService.links$.pipe(takeUntil(this.destroyed)).subscribe(links => {
this.hideToc = !links || links.length === 0;
this.updateScrollPosition();
if (!this.hideToc) {
this.tocService.scrollToAnchor(this.urlFragment);
}
});

this.tocService.activeLink$.pipe(takeUntil(this.destroyed)).subscribe(activeLink => {
this.activeLink = activeLink;
});
}

ngOnInit(): void {}

ngAfterViewInit() {
this.updateScrollPosition();
}

ngOnDestroy(): void {
this.destroyed.next();
}

updateScrollPosition(): void {
this.viewportScroller.scrollToAnchor(this.urlFragment);
}

onLinkClick($event: Event, link: TocLink) {
// 当前的 urlFragment 和点击相同,阻止默认行为,因为浏览器会按照整个文档可视区域滚动,
// 但是我们头部的导航会占用位置,viewportScroller 设置的 offset 为 [0, 60]
if (link.id === this.urlFragment) {
$event.preventDefault();
}
// if (link.id === this.urlFragment) {
// $event.preventDefault();
// }
}
}

0 comments on commit 6ebd0e5

Please sign in to comment.