From e42df1671bbbda66a028d26ab6d79f639fbef8f4 Mon Sep 17 00:00:00 2001 From: Paul Gschwendtner Date: Sat, 18 Nov 2017 13:51:16 +0100 Subject: [PATCH] fix: create proper fragment urls By default fragment links are referring to the root page and the actual hash won't matter anymore. This can be fixed in a similar way to the `header-link` directive by updating the anchor URLs to include the current base URL. Since those are normal links and aren't `header-links`, the `header-link` directive is not an option. A directive that updates the links accordingly would be perfect, but there is no way to interpolate directives on those HTML templates dynamically. Having a component that creates/wraps the anchor elements is wrong and adds more pain than it helps. The links should can be just updated using simple DOM manipulation. --- src/app/shared/doc-viewer/doc-viewer.ts | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/app/shared/doc-viewer/doc-viewer.ts b/src/app/shared/doc-viewer/doc-viewer.ts index c76c9e207..ec5c561dd 100644 --- a/src/app/shared/doc-viewer/doc-viewer.ts +++ b/src/app/shared/doc-viewer/doc-viewer.ts @@ -15,6 +15,7 @@ import {Subscription} from 'rxjs/Subscription'; import {ExampleViewer} from '../example-viewer/example-viewer'; import {HeaderLink} from './header-link'; import {ComponentPortal, DomPortalHost} from '@angular/cdk/portal'; +import {Router} from '@angular/router'; @Component({ selector: 'doc-viewer', @@ -40,7 +41,8 @@ export class DocViewer implements OnDestroy { private _elementRef: ElementRef, private _http: Http, private _injector: Injector, - private _viewContainerRef: ViewContainerRef) {} + private _viewContainerRef: ViewContainerRef, + private _router: Router) {} /** Fetch a document by URL. */ private _fetchDocument(url: string) { @@ -57,6 +59,7 @@ export class DocViewer implements OnDestroy { this.textContent = this._elementRef.nativeElement.textContent; this._loadComponents('material-docs-example', ExampleViewer); this._loadComponents('header-link', HeaderLink); + this._fixFragmentUrls(); this.contentLoaded.next(); } else { this._elementRef.nativeElement.innerText = @@ -100,6 +103,23 @@ export class DocViewer implements OnDestroy { this._portalHosts = []; } + /** + * A fragment link is a link that references a specific element on the page that should be + * scrolled into the viewport on page load or click. + * + * By default those links refer to the root page of the documentation and the fragment links + * won't work properly. Those links need to be updated to be relative to the current base URL. + */ + private _fixFragmentUrls() { + const baseUrl = this._router.url.split('#')[0]; + const anchorElements = + [].slice.call(this._elementRef.nativeElement.querySelectorAll('a')) as HTMLAnchorElement[]; + + anchorElements + .filter(anchorEl => anchorEl.hash) + .forEach(anchorEl => anchorEl.href = `${baseUrl}${anchorEl.hash}`); + } + ngOnDestroy() { this._clearLiveExamples();