我正在使用 ngx-markdown 来呈现我的常见问题解答,其中,我链接到外部资源(以
http
开头)和内部内容(以 /
开头)。
我想将角度路由器传递到我的markedOptionsFactory,以便将其用于本地资源。
有没有办法在导入模块时在装饰器中传递角度路由器:
imports: [
[...]
MarkdownModule.forRoot({
provide: MarkedOptions,
useFactory: markedOptionsFactory,
}),
[...]
],
仅供参考,我的
markedOptionsFactory
看起来像:
export function markedOptionsFactory(): MarkedOptions {
const renderer = new MarkedRenderer();
renderer.link = (href: string, title: string, text: string) => {
const isLocalLink = /^\//.test(href);
const target = isLocalLink ? '_self' : '_blank';
const hrefContent = isLocalLink ? `javascript:router.navigateByUrl('${href}')` : href;
return `<a href="${hrefContent}" target="${target}">${text}</a>`;
};
return {
renderer: renderer,
[...]
};
}
这是我的解决方案,基于建议这里
定义角度指令
import { Directive, HostListener } from '@angular/core';
import { Router } from "@angular/router";
@Directive({
selector: '[appInterceptRouterlink]'
})
export class InterceptRouterlinkDirective {
constructor(private router: Router) { }
@HostListener("click", ["$event"])
public onClick(e: MouseEvent): void {
const srcElem = e.target;
if (srcElem instanceof HTMLAnchorElement)
{
const baseURI = srcElem.baseURI ;
const href = srcElem.href ;
if (href.startsWith(baseURI))
{
const baseURILength = baseURI.length;
const routerlink = href.substring(baseURILength);
e.preventDefault();
e.stopPropagation();
this.router.navigate([routerlink]);
}
}
}
}
在 markdown 标签中使用指令,在我的例子中如下
<markdown [data]="markdown" appInterceptRouterlink></markdown>
指令中的 HostListener 查找以基本 URL 开头的链接并将它们作为路由器链接处理。
我没有从 Angular 找到直接的解决方案。我必须从 Marked.js 创建一个自定义事件,然后在 DOM 树中更高的位置捕获它。
这里是我工作的一些代码:
renderer.link = (href: string, title: string, text: string) => {
const isLocalLink = /^\//.test(href);
let hrefContent;
if (isLocalLink) {
hrefContent = `javascript:document.dispatchEvent(new CustomEvent('routeTo', {detail: '${href}'})); void(0)`;
} else {
hrefContent = href;
}
return `<a href="${hrefContent}">${text}</a>`;
};
this.window.document.addEventListener('routeTo', (e: CustomEvent) => {
e.preventDefault();
router.navigateByUrl(e.detail);
}, false);
小心使用 Internet Explorer,您将需要一个用于自定义事件的 Polyfill
您可以关注这个答案 希望这有帮助!
我不得不稍微修改菲尔斯的答案,但现在它也可以正常工作了。它无法正确处理片段。
@Component({
selector: 'app-markdown',
standalone: true,
templateUrl: './markdown.component.html',
styleUrl: './markdown.component.scss',
imports: [CommonModule, MarkedPipe],
})
export class MarkdownComponent {
private _router = inject(Router);
@Input({ required: true }) content!: string;
public onClick(e: MouseEvent): void {
const srcElem = e.target;
if (srcElem instanceof HTMLAnchorElement) {
const href = srcElem.href;
const isLocalLink = href.startsWith(srcElem.baseURI);
if (isLocalLink) {
e.preventDefault();
e.stopPropagation();
const url = new URL(href);
const fragment = url.hash ? url.hash.substring(1) : undefined;
this._router.navigate([url.pathname], { fragment });
}
}
}
}