feat(viewer): md 본문 외부 링크 새 탭 + rel 보안
문서 본문 markdown 의 외부 http(s) 링크(코퍼스 실측 521문서/9,496개)가 target/rel 없이 같은 탭으로 열려 SPA 를 이탈하던 문제 수정. MarkdownDoc 에 heading-anchor 와 동일한 DOM 후처리 $effect 추가 — sanitize 후 라이브 DOM 의 a[href^=http(s)] 에 target="_blank" + rel="noopener noreferrer" 부여. marked 렌더러/DOMPurify(전역 hook)· ADD_ATTR 무수정. 앵커(#)·상대경로·mailto 는 미변경(SPA 내부 항법 보존). 내부 위키링크([[...]])·백링크 그래프는 코퍼스 실측상 실신호 ~8개로 데이터 미지원이라 본 PR 범위에서 제외(보류, 내부 링크 증가가 트리거). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -160,6 +160,24 @@
|
||||
ph.dataset.mdImageSwapped = '1';
|
||||
}
|
||||
});
|
||||
|
||||
// 외부 http(s) 링크 → 새 탭(target=_blank) + 보안 rel(noopener noreferrer).
|
||||
// marked 렌더러/DOMPurify 를 건드리지 않고 sanitize 후 라이브 DOM 에 속성을 부여한다 —
|
||||
// heading anchor 와 동일한 DOM 후처리 패턴(전역 DOMPurify hook 오염·렌더러 API 의존 없이 안전).
|
||||
// 앵커(#)·상대경로·mailto 등 비-http(s) 링크는 손대지 않는다(SPA 내부 항법 보존).
|
||||
$effect(() => {
|
||||
void renderedHtml;
|
||||
if (!containerRef) return;
|
||||
const links = containerRef.querySelectorAll<HTMLAnchorElement>('a[href]');
|
||||
for (const a of links) {
|
||||
if (a.dataset.extlinkProcessed === '1') continue;
|
||||
const href = a.getAttribute('href') ?? '';
|
||||
if (!/^https?:\/\//i.test(href)) continue; // 외부 http(s) 만
|
||||
a.setAttribute('target', '_blank');
|
||||
a.setAttribute('rel', 'noopener noreferrer');
|
||||
a.dataset.extlinkProcessed = '1';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="mb-2">
|
||||
|
||||
Reference in New Issue
Block a user