mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-17 21:10:54 +00:00
Matrix: suppress auto-linked file refs
This commit is contained in:
@@ -14,6 +14,19 @@ describe("markdownToMatrixHtml", () => {
|
||||
expect(html).toContain('<a href="https://example.com">docs</a>');
|
||||
});
|
||||
|
||||
it("does not auto-link bare file references into external urls", () => {
|
||||
const html = markdownToMatrixHtml("Check README.md and backup.sh");
|
||||
expect(html).toContain("README.md");
|
||||
expect(html).toContain("backup.sh");
|
||||
expect(html).not.toContain('href="http://README.md"');
|
||||
expect(html).not.toContain('href="http://backup.sh"');
|
||||
});
|
||||
|
||||
it("keeps real domains linked even when path segments look like filenames", () => {
|
||||
const html = markdownToMatrixHtml("See https://docs.example.com/backup.sh");
|
||||
expect(html).toContain('href="https://docs.example.com/backup.sh"');
|
||||
});
|
||||
|
||||
it("escapes raw HTML", () => {
|
||||
const html = markdownToMatrixHtml("<b>nope</b>");
|
||||
expect(html).toContain("<b>nope</b>");
|
||||
|
||||
@@ -11,10 +11,63 @@ md.enable("strikethrough");
|
||||
|
||||
const { escapeHtml } = md.utils;
|
||||
|
||||
/**
|
||||
* Keep bare file references like README.md from becoming external http:// links.
|
||||
* Telegram already hardens this path; Matrix should not turn common code/docs
|
||||
* filenames into clickable registrar-style URLs either.
|
||||
*/
|
||||
const FILE_EXTENSIONS_WITH_TLD = new Set(["md", "go", "py", "pl", "sh", "am", "at", "be", "cc"]);
|
||||
|
||||
function isAutoLinkedFileRef(href: string, label: string): boolean {
|
||||
const stripped = href.replace(/^https?:\/\//i, "");
|
||||
if (stripped !== label) {
|
||||
return false;
|
||||
}
|
||||
const dotIndex = label.lastIndexOf(".");
|
||||
if (dotIndex < 1) {
|
||||
return false;
|
||||
}
|
||||
const ext = label.slice(dotIndex + 1).toLowerCase();
|
||||
if (!FILE_EXTENSIONS_WITH_TLD.has(ext)) {
|
||||
return false;
|
||||
}
|
||||
const segments = label.split("/");
|
||||
if (segments.length > 1) {
|
||||
for (let i = 0; i < segments.length - 1; i += 1) {
|
||||
if (segments[i]?.includes(".")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function shouldSuppressAutoLink(
|
||||
tokens: Parameters<NonNullable<typeof md.renderer.rules.link_open>>[0],
|
||||
idx: number,
|
||||
): boolean {
|
||||
const token = tokens[idx];
|
||||
if (token?.type !== "link_open" || token.info !== "auto") {
|
||||
return false;
|
||||
}
|
||||
const href = token.attrGet("href") ?? "";
|
||||
const label = tokens[idx + 1]?.type === "text" ? (tokens[idx + 1]?.content ?? "") : "";
|
||||
return Boolean(href && label && isAutoLinkedFileRef(href, label));
|
||||
}
|
||||
|
||||
md.renderer.rules.image = (tokens, idx) => escapeHtml(tokens[idx]?.content ?? "");
|
||||
|
||||
md.renderer.rules.html_block = (tokens, idx) => escapeHtml(tokens[idx]?.content ?? "");
|
||||
md.renderer.rules.html_inline = (tokens, idx) => escapeHtml(tokens[idx]?.content ?? "");
|
||||
md.renderer.rules.link_open = (tokens, idx, _options, _env, self) =>
|
||||
shouldSuppressAutoLink(tokens, idx) ? "" : self.renderToken(tokens, idx, _options);
|
||||
md.renderer.rules.link_close = (tokens, idx, _options, _env, self) => {
|
||||
const openIdx = idx - 2;
|
||||
if (openIdx >= 0 && shouldSuppressAutoLink(tokens, openIdx)) {
|
||||
return "";
|
||||
}
|
||||
return self.renderToken(tokens, idx, _options);
|
||||
};
|
||||
|
||||
export function markdownToMatrixHtml(markdown: string): string {
|
||||
const rendered = md.render(markdown ?? "");
|
||||
|
||||
Reference in New Issue
Block a user