elements
elements copied to clipboard
Anchor links from articles not working in Elements Dev Portal
The anchor links from any articles written in the Stoplight platform do not work correctly in Angular. The basePath value from the elements component is not considered in the anchor link.
Similar to https://github.com/stoplightio/elements/issues/1699 and https://github.com/stoplightio/elements/issues/2133
Context
- Consider docs hosted at
example.com/docsand an article atexample.com/docs/article - Any anchor links in the article will point at
example.com/#anchorinstead ofexample.com/docs/article#anchor - Not only is the link incorrect, it might navigate users away from the documentation
Current Behavior
- Anchor link is incorrect
- Article anchor links do not consider the basePath of the component
<elements-stoplight-project
projectId="..."
basePath="/api/docs" // this is not reflected in anchor links
></elements-stoplight-project>
Expected Behavior
- Anchor link should be correct
- Clicking should scroll to the correct section instead of navigating to a different page
Possible Workaround/Solution
As a workaround I directly modify anchor tags in my component, it works but shouldn't be necessary
export class ApiPortalComponent implements AfterViewInit {
private mutationObserver: MutationObserver;
public basePath = '/docs/api';
private elementsQuerySelector = 'elements-stoplight-project';
constructor(private router: Router, private renderer: Renderer2, private el: ElementRef) {}
ngAfterViewInit() {
this.updateAnchorLinks();
this.mutationObserver = new MutationObserver(() => {
this.updateAnchorLinks();
});
const targetNode = this.el.nativeElement.querySelector(this.elementsQuerySelector);
if (targetNode) {
this.mutationObserver.observe(targetNode, {
childList: true,
subtree: true,
});
}
}
ngOnDestroy() {
if (this.mutationObserver) {
this.mutationObserver.disconnect();
}
}
/**
* Fixes an issue where anchor links are not working as expected in Stoplight Elements Dev Portal
* https://github.com/stoplightio/elements/issues/1699
* https://github.com/stoplightio/elements/issues/2133
*
* The anchor links do not contain the base path of the API portal, so we need to update them.
* Loop through all anchor links in the API portal and update the href attribute to include the base path.
* Also fixes the issue where the page refreshes when clicking on an anchor link.
*/
public updateAnchorLinks() {
const anchorLinks = this.el.nativeElement.querySelectorAll(`${this.elementsQuerySelector} a[href^="#"]`);
anchorLinks.forEach((link: HTMLAnchorElement) => {
const anchor = link.getAttribute('href')?.split('#')[1];
if (anchor && link.href.indexOf(this.basePath) === -1) {
this.renderer.setAttribute(link, 'href', `${this.basePath}#${anchor}`);
// Add click event listener to prevent full page refresh and scroll to the anchor
this.renderer.listen(link, 'click', (event) => {
event.preventDefault();
void this.router.navigate([this.basePath], { fragment: anchor }).then(() => {
this.scrollToAnchor(anchor);
});
});
}
});
}
private scrollToAnchor(anchor: string) {
const element = document.getElementById(anchor);
if (element) {
element.scrollIntoView({ behavior: 'smooth' });
}
}
}
Steps to Reproduce
- Run elements dev portal locally, ensure there is a
basePathspecified in the component - Write an article which includes headings
- Navigate to the article in the dev portal, click a link on the right side
Environment
- Version used:
"@stoplight/elements-dev-portal": "2.2.0" - Environment name and version (e.g. Chrome 39, node.js 5.4): Chrome
- Operating System and version (desktop or mobile): Both