Files
multica/apps/mobile/lib/markdown/preprocess.test.ts
YYClaw d09019cd95 MUL-5839: preserve media in /issue descriptions (#6536)
* fix(channel): preserve images in issue descriptions

* fix(views): hide channel-media provenance in board card previews

descriptionPreview strips image Markdown but not HTML comments, so a
`/issue` description whose media was materialized rendered its provenance
marker as the card's visible preview text. cardProperties.description
defaults to true, so this showed on the default board view for every issue
created from a channel message carrying an image.

Co-authored-by: multica-agent <github@multica.ai>

---------

Co-authored-by: J <j@multica.ai>
Co-authored-by: multica-agent <github@multica.ai>
2026-08-07 15:35:59 +08:00

63 lines
2.7 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { preprocessMobileMarkdown } from "./preprocess";
const UUID = "019f49e2-5b07-7970-beef-c0d537fb8c1d";
const ABS_URL = `https://multica-app.copilothub.ai/api/attachments/${UUID}/download`;
const REL_URL = `/api/attachments/${UUID}/download`;
describe("preprocessMobileMarkdown — !file file cards", () => {
it("keeps channel images visible while hiding their provenance marker", () => {
const image = `![](${REL_URL})`;
const marker = `<!-- multica:channel-media:${UUID} -->`;
expect(preprocessMobileMarkdown(`${image}\n\n${marker}`)).toBe(`${image}\n\n`);
});
it("matches the CLI's escaped-bracket label and keeps it markdown-safe", () => {
// CLI emits `a]b.pdf` escaped as `a\]b.pdf` (cmd_attachment.go
// escapeMarkdownLabel). The old regex stopped at the first `]` and left the
// line literal; now it is captured whole and re-emitted as a tappable link
// whose label stays escaped so the `]` doesn't truncate the link text.
const out = preprocessMobileMarkdown(`!file[a\\]b.pdf](${ABS_URL})`);
expect(out).toBe(`[📎 a\\]b.pdf](${ABS_URL})`);
});
it("unescapes non-breaking metacharacters (parens) in the displayed name", () => {
// Parens are legal inside a markdown link label, so they are unescaped for
// display and not re-escaped.
const out = preprocessMobileMarkdown(`!file[report\\(1\\).pdf](${ABS_URL})`);
expect(out).toBe(`[📎 report(1).pdf](${ABS_URL})`);
});
it("unescapes an escaped backslash in the label", () => {
const out = preprocessMobileMarkdown(`!file[a\\\\b.pdf](${ABS_URL})`);
expect(out).toBe(`[📎 a\\\\b.pdf](${ABS_URL})`);
});
it("renders a plain (unescaped) label", () => {
const out = preprocessMobileMarkdown(`!file[notes.txt](${ABS_URL})`);
expect(out).toBe(`[📎 notes.txt](${ABS_URL})`);
});
it("accepts the site-relative /api/attachments URL form (web parity)", () => {
const out = preprocessMobileMarkdown(`!file[a.pdf](${REL_URL})`);
expect(out).toBe(`[📎 a.pdf](${REL_URL})`);
});
it("leaves a disallowed-scheme URL as plain text (no out-of-band navigation)", () => {
const line = `!file[x.pdf](javascript:alert(1))`;
expect(preprocessMobileMarkdown(line)).toBe(line);
});
it("does not touch inline images (![...] is not a file card)", () => {
const line = `![chart.png](${ABS_URL})`;
expect(preprocessMobileMarkdown(line)).toBe(line);
});
it("only transforms the standalone file-card line, leaving surrounding text", () => {
const input = `here is the file\n\n!file[a\\]b.pdf](${ABS_URL})\n\nlet me know`;
const output = `here is the file\n\n[📎 a\\]b.pdf](${ABS_URL})\n\nlet me know`;
expect(preprocessMobileMarkdown(input)).toBe(output);
});
});