UNPKG

@gguf/claw

Version:

Multi-channel AI gateway with extensible messaging integrations

104 lines (103 loc) 3.29 kB
//#region src/markdown/render.ts const STYLE_RANK = new Map([ "blockquote", "code_block", "code", "bold", "italic", "strikethrough", "spoiler" ].map((style, index) => [style, index])); function sortStyleSpans(spans) { return [...spans].toSorted((a, b) => { if (a.start !== b.start) return a.start - b.start; if (a.end !== b.end) return b.end - a.end; return (STYLE_RANK.get(a.style) ?? 0) - (STYLE_RANK.get(b.style) ?? 0); }); } function renderMarkdownWithMarkers(ir, options) { const text = ir.text ?? ""; if (!text) return ""; const styleMarkers = options.styleMarkers; const styled = sortStyleSpans(ir.styles.filter((span) => Boolean(styleMarkers[span.style]))); const boundaries = /* @__PURE__ */ new Set(); boundaries.add(0); boundaries.add(text.length); const startsAt = /* @__PURE__ */ new Map(); for (const span of styled) { if (span.start === span.end) continue; boundaries.add(span.start); boundaries.add(span.end); const bucket = startsAt.get(span.start); if (bucket) bucket.push(span); else startsAt.set(span.start, [span]); } for (const spans of startsAt.values()) spans.sort((a, b) => { if (a.end !== b.end) return b.end - a.end; return (STYLE_RANK.get(a.style) ?? 0) - (STYLE_RANK.get(b.style) ?? 0); }); const linkStarts = /* @__PURE__ */ new Map(); if (options.buildLink) for (const link of ir.links) { if (link.start === link.end) continue; const rendered = options.buildLink(link, text); if (!rendered) continue; boundaries.add(rendered.start); boundaries.add(rendered.end); const openBucket = linkStarts.get(rendered.start); if (openBucket) openBucket.push(rendered); else linkStarts.set(rendered.start, [rendered]); } const points = [...boundaries].toSorted((a, b) => a - b); const stack = []; let out = ""; for (let i = 0; i < points.length; i += 1) { const pos = points[i]; while (stack.length && stack[stack.length - 1]?.end === pos) { const item = stack.pop(); if (item) out += item.close; } const openingItems = []; const openingLinks = linkStarts.get(pos); if (openingLinks && openingLinks.length > 0) for (const [index, link] of openingLinks.entries()) openingItems.push({ end: link.end, open: link.open, close: link.close, kind: "link", index }); const openingStyles = startsAt.get(pos); if (openingStyles) for (const [index, span] of openingStyles.entries()) { const marker = styleMarkers[span.style]; if (!marker) continue; openingItems.push({ end: span.end, open: marker.open, close: marker.close, kind: "style", style: span.style, index }); } if (openingItems.length > 0) { openingItems.sort((a, b) => { if (a.end !== b.end) return b.end - a.end; if (a.kind !== b.kind) return a.kind === "link" ? -1 : 1; if (a.kind === "style" && b.kind === "style") return (STYLE_RANK.get(a.style) ?? 0) - (STYLE_RANK.get(b.style) ?? 0); return a.index - b.index; }); for (const item of openingItems) { out += item.open; stack.push({ close: item.close, end: item.end }); } } const next = points[i + 1]; if (next === void 0) break; if (next > pos) out += options.escapeText(text.slice(pos, next)); } return out; } //#endregion export { renderMarkdownWithMarkers as t };