import {
chunkMarkdownIR,
markdownToIR,
type MarkdownLinkSpan,
type MarkdownIR,
} from "../markdown/ir.js";
import { renderMarkdownWithMarkers } from "../markdown/render.js";
export type TelegramFormattedChunk = {
html: string;
text: string;
};
function escapeHtml(text: string): string {
return text.replace(/&/g, "&").replace(//g, ">");
}
function escapeHtmlAttr(text: string): string {
return escapeHtml(text).replace(/"/g, """);
}
function buildTelegramLink(link: MarkdownLinkSpan, _text: string) {
const href = link.href.trim();
if (!href) return null;
if (link.start === link.end) return null;
const safeHref = escapeHtmlAttr(href);
return {
start: link.start,
end: link.end,
open: ``,
close: "",
};
}
function renderTelegramHtml(ir: MarkdownIR): string {
return renderMarkdownWithMarkers(ir, {
styleMarkers: {
bold: { open: "", close: "" },
italic: { open: "", close: "" },
strikethrough: { open: "", close: "" },
code: { open: "", close: "" },
code_block: { open: "
", close: "" },
},
escapeText: escapeHtml,
buildLink: buildTelegramLink,
});
}
export function markdownToTelegramHtml(markdown: string): string {
const ir = markdownToIR(markdown ?? "", {
linkify: true,
headingStyle: "none",
blockquotePrefix: "",
});
return renderTelegramHtml(ir);
}
export function markdownToTelegramChunks(
markdown: string,
limit: number,
): TelegramFormattedChunk[] {
const ir = markdownToIR(markdown ?? "", {
linkify: true,
headingStyle: "none",
blockquotePrefix: "",
});
const chunks = chunkMarkdownIR(ir, limit);
return chunks.map((chunk) => ({
html: renderTelegramHtml(chunk),
text: chunk.text,
}));
}
export function markdownToTelegramHtmlChunks(markdown: string, limit: number): string[] {
return markdownToTelegramChunks(markdown, limit).map((chunk) => chunk.html);
}