master @ 49 LINES
[ HISTORY ] [ UP ]
┌─ ASTRO ────────────────────────────────────────────────────────────────────┐
│ --- │
│ // Emits the same markup as the ```diff pipeline output, so Prose's │
│ // code-block styles and the layout's copy handler apply unchanged. │
│ // Assembled as an HTML string: the Astro compiler can't nest expression │
│ // children inside a raw <pre> tag. │
│ import { G } from "../../lib/ascii"; │
│ import { FRAME_W, MOBILE_FRAME_W } from "../../lib/config"; │
│ import { layoutDiff, type Props } from "./Diff"; │
│ // The wrapper carries .prose so these selectors match - without the │
│ // import, pages that never render Prose leave the copy button and │
│ // diff classes unstyled. │
│ import "../Prose/Prose.scss"; │
│ │
│ const { code } = Astro.props as Props; │
│ const raw = code.replace(/\n+$/, ""); │
│ │
│ const esc = (s: string) => │
│ s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); │
│ const frame = (s: string) => │
│ `<span class="code-frame" aria-hidden="true">${esc(s)}</span>`; │
│ │
│ function renderCode(w: number): string { │
│ const parts: string[] = [ │
│ frame(G.TL + G.H + " DIFF " + G.H.repeat(w - 12 - 6)), │
│ '<button type="button" class="code-copy" aria-label="Copy code">[ COPY ]</butt │
│ on>', │
│ frame(G.H + G.TR), │
│ "\n", │
│ ]; │
│ for (const r of layoutDiff(code, w)) { │
│ parts.push(frame(G.V + " ")); │
│ parts.push(r.cls ? `<span class="${r.cls}">${esc(r.text)}</span>` : esc(r.text │
│ )); │
│ parts.push(frame(" ".repeat(r.pad) + " " + G.V)); │
│ parts.push("\n"); │
│ } │
│ parts.push(frame(G.BL + G.H.repeat(w - 2) + G.BR)); │
│ return `<code>${parts.join("")}</code>`; │
│ } │
│ │
│ const variants = [ │
│ { cls: "frame-wide", w: FRAME_W }, │
│ { cls: "frame-narrow", w: MOBILE_FRAME_W }, │
│ ]; │
│ --- │
│ <div class="code-frames prose"> │
│ {variants.map(({ cls, w }) => ( │
│ <pre class={"ascii code-block " + cls} data-raw-code={raw} set:html={renderCod │
│ e(w)} /> │
│ ))} │
│ </div> │
└────────────────────────────────────────────────────────────────────────────────────┘
┌─ ASTRO ──────────────────────────────┐
│ --- │
│ // Emits the same markup as the ```diff pipe │
│ line output, so Prose's │
│ // code-block styles and the layout's copy h │
│ andler apply unchanged. │
│ // Assembled as an HTML string: the Astro co │
│ mpiler can't nest expression │
│ // children inside a raw <pre> tag. │
│ import { G } from "../../lib/ascii"; │
│ import { FRAME_W, MOBILE_FRAME_W } from "../ │
│ ../lib/config"; │
│ import { layoutDiff, type Props } from "./Di │
│ ff"; │
│ // The wrapper carries .prose so these selec │
│ tors match - without the │
│ // import, pages that never render Prose lea │
│ ve the copy button and │
│ // diff classes unstyled. │
│ import "../Prose/Prose.scss"; │
│ │
│ const { code } = Astro.props as Props; │
│ const raw = code.replace(/\n+$/, ""); │
│ │
│ const esc = (s: string) => │
│ s.replace(/&/g, "&").replace(/</g, "&l │
│ t;").replace(/>/g, ">"); │
│ const frame = (s: string) => │
│ `<span class="code-frame" aria-hidden="tru │
│ e">${esc(s)}</span>`; │
│ │
│ function renderCode(w: number): string { │
│ const parts: string[] = [ │
│ frame(G.TL + G.H + " DIFF " + G.H.repeat │
│ (w - 12 - 6)), │
│ '<button type="button" class="code-copy" │
│ aria-label="Copy code">[ COPY ]</button>', │
│ frame(G.H + G.TR), │
│ "\n", │
│ ]; │
│ for (const r of layoutDiff(code, w)) { │
│ parts.push(frame(G.V + " ")); │
│ parts.push(r.cls ? `<span class="${r.cls │
│ }">${esc(r.text)}</span>` : esc(r.text)); │
│ parts.push(frame(" ".repeat(r.pad) + " " │
│ + G.V)); │
│ parts.push("\n"); │
│ } │
│ parts.push(frame(G.BL + G.H.repeat(w - 2) │
│ + G.BR)); │
│ return `<code>${parts.join("")}</code>`; │
│ } │
│ │
│ const variants = [ │
│ { cls: "frame-wide", w: FRAME_W }, │
│ { cls: "frame-narrow", w: MOBILE_FRAME_W } │
│ , │
│ ]; │
│ --- │
│ <div class="code-frames prose"> │
│ {variants.map(({ cls, w }) => ( │
│ <pre class={"ascii code-block " + cls} d │
│ ata-raw-code={raw} set:html={renderCode(w)} │
│ /> │
│ ))} │
│ </div> │
└──────────────────────────────────────────────┘
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET