Files
openclaw/src/markdown/tables.ts
Vincent Koc 54f7221465 fix(slack): restore table block mode seam (#57591)
* fix(slack): restore table block mode seam

Restore the shared markdown/config seam needed for Slack Block Kit table support, while coercing non-Slack block mode back to code.

* fix(slack): narrow table block seam defaults

Keep Slack table block mode opt-in in this seam-only PR, clamp collected placeholder offsets, and align fallback-table rendering with Slack block limits.

* fix(slack): bound table fallback rendering

Avoid spread-based maxima and bound Slack table fallback rendering by row, column, cell-width, and total-output limits to prevent resource exhaustion.

* fix(slack): keep block mode inactive in seam PR

Keep markdown table block mode schema-valid but runtime-resolved to code until the Slack send path is wired to emit table attachments.

* fix(slack): normalize configured block mode safely

Accept configured markdown table block mode at parse time, then normalize it back to code during runtime resolution so seam-only branches do not drop table content.
2026-03-30 19:25:01 +09:00

44 lines
1.3 KiB
TypeScript

import type { MarkdownTableMode } from "../config/types.base.js";
import { markdownToIRWithMeta } from "./ir.js";
import { renderMarkdownWithMarkers } from "./render.js";
const MARKDOWN_STYLE_MARKERS = {
bold: { open: "**", close: "**" },
italic: { open: "_", close: "_" },
strikethrough: { open: "~~", close: "~~" },
code: { open: "`", close: "`" },
code_block: { open: "```\n", close: "```" },
} as const;
export function convertMarkdownTables(markdown: string, mode: MarkdownTableMode): string {
if (!markdown || mode === "off") {
return markdown;
}
const effectiveMode = mode === "block" ? "code" : mode;
const { ir, hasTables } = markdownToIRWithMeta(markdown, {
linkify: false,
autolink: false,
headingStyle: "none",
blockquotePrefix: "",
tableMode: effectiveMode,
});
if (!hasTables) {
return markdown;
}
return renderMarkdownWithMarkers(ir, {
styleMarkers: MARKDOWN_STYLE_MARKERS,
escapeText: (text) => text,
buildLink: (link, text) => {
const href = link.href.trim();
if (!href) {
return null;
}
const label = text.slice(link.start, link.end);
if (!label) {
return null;
}
return { start: link.start, end: link.end, open: "[", close: `](${href})` };
},
});
}