Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| db7ede04b7 |
@@ -126,11 +126,49 @@ function _protectMath(text: string, slots: string[]): string {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── 이미지 pre-render ─────────────────────────────────────────────────────────
|
||||||
|
// docMarked 의 image 렌더러(.use renderer)가 런타임에 미발화하면 `` 가
|
||||||
|
// 기본 `<img src="docimg:..">` 로 떨어지고, DOMPurify(ALLOW_UNKNOWN_PROTOCOLS:false)가
|
||||||
|
// `docimg:` 를 미지원 프로토콜로 제거 → placeholder 도 이미지도 둘 다 사라진다(수식 토크나이저
|
||||||
|
// 미발화와 동형 증상). → marked 가 손대기 전에 image ref 를 placeholder figure 로 직접 변환해
|
||||||
|
// 슬롯 보호(렌더러 발화 여부와 무관). 슬롯/복원 메커니즘은 수식과 공유.
|
||||||
|
const _IMG_RE = /!\[([^\]]*)\]\(([^)\s]+)\)/g;
|
||||||
|
|
||||||
|
function _imagePlaceholder(alt: string, href: string): string {
|
||||||
|
const isInternal = href.startsWith('docimg:');
|
||||||
|
const basename = href.split('/').pop() ?? href;
|
||||||
|
const labelSrc = alt || basename || '이미지';
|
||||||
|
const safeHref = escAttr(href);
|
||||||
|
const safeAlt = escAttr(alt);
|
||||||
|
const safeLabel = escText(`[이미지: ${labelSrc} — 아직 표시되지 않음]`);
|
||||||
|
const internalFlag = isInternal ? '1' : '0';
|
||||||
|
return (
|
||||||
|
`<figure class="md-image-placeholder" data-md-img="1" data-md-image-src="${safeHref}" data-md-image-internal="${internalFlag}" data-md-image-alt="${safeAlt}">` +
|
||||||
|
`<div class="md-image-placeholder-card">` +
|
||||||
|
`<span class="md-image-placeholder-icon" aria-hidden="true">🖼️</span>` +
|
||||||
|
`<span class="md-image-placeholder-label">${safeLabel}</span>` +
|
||||||
|
`</div>` +
|
||||||
|
`</figure>`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _protectImages(text: string, slots: string[]): string {
|
||||||
|
return text.replace(_IMG_RE, (m, alt, href) => {
|
||||||
|
try {
|
||||||
|
slots.push(_imagePlaceholder(String(alt ?? ''), String(href ?? '')));
|
||||||
|
return _MATH_SLOT(slots.length - 1);
|
||||||
|
} catch {
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function renderDocMarkdown(text: string | null | undefined): string {
|
export function renderDocMarkdown(text: string | null | undefined): string {
|
||||||
if (!text) return '';
|
if (!text) return '';
|
||||||
try {
|
try {
|
||||||
const slots: string[] = [];
|
const slots: string[] = [];
|
||||||
const protectedText = _protectMath(text, slots);
|
// 이미지 먼저 placeholder 로 pre-render(렌더러 우회) → 그 다음 수식. 슬롯 공유.
|
||||||
|
const protectedText = _protectMath(_protectImages(text, slots), slots);
|
||||||
let html = docMarked.parse(protectedText) as string;
|
let html = docMarked.parse(protectedText) as string;
|
||||||
if (slots.length) {
|
if (slots.length) {
|
||||||
// 블록 수식이 단독 문단이면 marked 가 <p> 로 감싸므로 그 <p> 를 벗겨 블록 수식이 문단에
|
// 블록 수식이 단독 문단이면 marked 가 <p> 로 감싸므로 그 <p> 를 벗겨 블록 수식이 문단에
|
||||||
|
|||||||
Reference in New Issue
Block a user