/**
* The elements a page emits for a resolved Markdown link or image.
*
* Two renderers reach a link: the Markdown renderer (`markdown.ts`) and the raw-HTML
* sanitizer (`raw-html.ts`). Both ask `urls.ts` what a destination resolves to, and both
* then build the same anchor and the same image — the external-rel attributes, the
* `md-img` class, and the lazy decoding — so those live here rather than in a fourth and
* fifth copy. Values are escaped here; the callers hand in what the document said.
*/
import { escapeHtml } from "../../../lib/escape.ts";
/**
* The attributes an external link carries, for a caller that is building the element
* itself: the raw-HTML sanitizer rewrites an existing tag's attribute list and has no
* content string to hand an emitter.
*
* `noopener` because the target is another origin, and `noreferrer` because the page is a
* local view of the reader's own repository and should not tell anyone where they read it.
*/
export const EXTERNAL_ATTRS = ' target="_blank" rel="noopener noreferrer"';
/** An `` for one destination; `title` and the rel attributes are omitted when absent. */
export function emitAnchor(input: { href: string; content: string; title?: string; external: boolean }): string {
const title = input.title === undefined ? "" : ` title="${escapeHtml(input.title)}"`;
return `${input.content}`;
}
/**
* A link standing in for an image the page may not show: an external `src` is blocked by
* the CSP, so the reader gets something to click, labelled by the alt text.
*/
export function emitImageLink(href: string, label: string): string {
return `${escapeHtml(label)}`;
}
/** An `
`: block-level spacing class, alt text, and the sizes a document may pin. */
export function emitImage(input: {
href: string;
alt: string;
title?: string;
/** A document may pin a pixel size; escaped like every other value the page emits. */
width?: string | number;
height?: string | number;
}): string {
const size = `${input.width === undefined ? "" : ` width="${escapeHtml(String(input.width))}"`}${
input.height === undefined ? "" : ` height="${escapeHtml(String(input.height))}"`
}`;
const title = input.title === undefined ? "" : ` title="${escapeHtml(input.title)}"`;
return `
`;
}