diff --git a/m2d/converters/event-to-message.js b/m2d/converters/event-to-message.js index f793f85..7893799 100644 --- a/m2d/converters/event-to-message.js +++ b/m2d/converters/event-to-message.js @@ -10,7 +10,6 @@ const { sync, db, discord } = passthrough /** @type {import("../../matrix/file")} */ const file = sync.require("../../matrix/file") -// https://github.com/mixmark-io/turndown/blob/97e4535ca76bb2e70d9caa2aa4d4686956b06d44/src/utilities.js#L26C28-L33C2 const BLOCK_ELEMENTS = [ "ADDRESS", "ARTICLE", "ASIDE", "AUDIO", "BLOCKQUOTE", "BODY", "CANVAS", "CENTER", "DD", "DETAILS", "DIR", "DIV", "DL", "DT", "FIELDSET", "FIGCAPTION", "FIGURE", @@ -21,7 +20,10 @@ const BLOCK_ELEMENTS = [ ] const turndownService = new TurndownService({ - hr: "----" + hr: "----", + headingStyle: "atx", + preformattedCode: true, + codeBlockStyle: "fenced" }) turndownService.addRule("strikethrough", { @@ -81,6 +83,10 @@ function eventToMessage(event) { // It's optimised for commonmark, we need to replace the space-space-newline with just newline content = content.replace(/ \n/g, "\n") + } else { + // Looks like we're using the plaintext body! + // Markdown needs to be escaped + content = content.replace(/([*_~`#])/g, `\\$1`) } // Split into 2000 character chunks diff --git a/m2d/converters/event-to-message.test.js b/m2d/converters/event-to-message.test.js index ac62bf3..7aefdb1 100644 --- a/m2d/converters/event-to-message.test.js +++ b/m2d/converters/event-to-message.test.js @@ -10,11 +10,11 @@ function sameFirstContentAndWhitespace(t, a, b) { t.equal(a2, b2) } -test("event2message: janky test", t => { +test("event2message: body is used when there is no formatted_body", t => { t.deepEqual( eventToMessage({ content: { - body: "test", + body: "testing plaintext", msgtype: "m.text" }, event_id: "$g07oYSZFWBkxohNEfywldwgcWj1hbhDzQ1sBAKvqOOU", @@ -28,7 +28,31 @@ test("event2message: janky test", t => { }), [{ username: "cadence", - content: "test", + content: "testing plaintext", + avatar_url: undefined + }] + ) +}) + +test("event2message: any markdown in body is escaped", t => { + t.deepEqual( + eventToMessage({ + content: { + body: "testing **special** ~~things~~ which _should_ *not* `trigger` @any ", + msgtype: "m.text" + }, + event_id: "$g07oYSZFWBkxohNEfywldwgcWj1hbhDzQ1sBAKvqOOU", + origin_server_ts: 1688301929913, + room_id: "!kLRqKKUQXcibIMtOpl:cadence.moe", + sender: "@cadence:cadence.moe", + type: "m.room.message", + unsigned: { + age: 405299 + } + }), + [{ + username: "cadence", + content: "testing \\*\\*special\\*\\* \\~\\~things\\~\\~ which \\_should\\_ \\*not\\* \\`trigger\\` @any ", avatar_url: undefined }] ) @@ -221,6 +245,33 @@ test("event2message: long messages are split", t => { ) }) +test("event2message: code blocks work", t => { + t.deepEqual( + eventToMessage({ + content: { + msgtype: "m.text", + body: "wrong body", + format: "org.matrix.custom.html", + formatted_body: "

preceding

\n
code block\n
\n

following code is inline

\n" + }, + event_id: "$g07oYSZFWBkxohNEfywldwgcWj1hbhDzQ1sBAKvqOOU", + origin_server_ts: 1688301929913, + room_id: "!kLRqKKUQXcibIMtOpl:cadence.moe", + sender: "@cadence:cadence.moe", + type: "m.room.message", + unsigned: { + age: 405299 + } + }), + [{ + username: "cadence", + content: "preceding\n\n```\ncode block\n```\n\nfollowing `code` is inline", + avatar_url: undefined + }] + ) +}) + + test("event2message: m.emote markdown syntax is escaped", t => { t.deepEqual( eventToMessage({