diff --git a/src/discord/utils.js b/src/discord/utils.js index aed7068..0d400f1 100644 --- a/src/discord/utils.js +++ b/src/discord/utils.js @@ -182,6 +182,394 @@ function filterTo(xs, fn) { return filtered } +const supportedPlaintextPreviewExtensions = new Set([ + "4d", + "abnf", + "accesslog", + "actionscript", + "ada", + "adoc", + "alan", + "angelscript", + "ansi", + "apache", + "apacheconf", + "applescript", + "arcade", + "arduino", + "arm", + "armasm", + "as", + "asc", + "asciidoc", + "aspectj", + "ass", + "atom", + "autohotkey", + "autoit", + "avrasm", + "awk", + "axapta", + "bash", + "basic", + "bat", + "bbcode", + "bf", + "bind", + "blade", + "bnf", + "brainfuck", + "c", + "c++", + "cal", + "capnp", + "capnproto", + "cc", + "chaos", + "chapel", + "chpl", + "cisco", + "clj", + "clojure", + "cls", + "cmake.in", + "cmake", + "cmd", + "coffee", + "coffeescript", + "console", + "coq", + "cos", + "cpc", + "cpp", + "cr", + "craftcms", + "crm", + "crmsh", + "crystal", + "cs", + "csharp", + "cshtml", + "cson", + "csp", + "css", + "csv", + "cxx", + "cypher", + "d", + "dart", + "delphi", + "dfm", + "diff", + "django", + "dns", + "docker", + "dockerfile", + "dos", + "dpr", + "dsconfig", + "dst", + "dts", + "dust", + "dylan", + "ebnf", + "elixir", + "elm", + "erl", + "erlang", + "ex", + "extempore", + "f90", + "f95", + "fix", + "fortran", + "freepascal", + "fs", + "fsharp", + "gams", + "gauss", + "gawk", + "gcode", + "gdscript", + "gemspec", + "gf", + "gherkin", + "glsl", + "gms", + "gn", + "gni", + "go", + "godot", + "golang", + "golo", + "gololang", + "gradle", + "graph", + "groovy", + "gss", + "gyp", + "h", + "h++", + "haml", + "handlebars", + "haskell", + "haxe", + "hbs", + "hcl", + "hh", + "hpp", + "hs", + "html.handlebars", + "html.hbs", + "html", + "http", + "https", + "hx", + "hxx", + "hy", + "hylang", + "i", + "i7", + "iced", + "iecst", + "inform7", + "ini", + "ino", + "instances", + "iol", + "irb", + "irpf90", + "java", + "javascript", + "jinja", + "jolie", + "js", + "json", + "jsp", + "jsx", + "julia-repl", + "julia", + "k", + "kaos", + "kdb", + "kotlin", + "kt", + "lasso", + "lassoscript", + "lazarus", + "ldif", + "leaf", + "lean", + "less", + "lfm", + "lisp", + "livecodeserver", + "livescript", + "ln", + "lock", + "log", + "lpr", + "ls", + "ls", + "lua", + "mak", + "make", + "makefile", + "markdown", + "mathematica", + "matlab", + "mawk", + "maxima", + "md", + "mel", + "mercury", + "mirc", + "mizar", + "mk", + "mkd", + "mkdown", + "ml", + "ml", + "mm", + "mma", + "mojolicious", + "monkey", + "moon", + "moonscript", + "mrc", + "n1ql", + "nawk", + "nc", + "never", + "nginx", + "nginxconf", + "nim", + "nimrod", + "nix", + "nsis", + "obj-c", + "obj-c++", + "objc", + "objective-c++", + "objectivec", + "ocaml", + "ocl", + "ol", + "openscad", + "osascript", + "oxygene", + "p21", + "parser3", + "pas", + "pascal", + "patch", + "pcmk", + "perl", + "pf.conf", + "pf", + "pgsql", + "php", + "php3", + "php4", + "php5", + "php6", + "php7", + "pl", + "plaintext", + "plist", + "pm", + "podspec", + "pony", + "postgres", + "postgresql", + "powershell", + "pp", + "processing", + "profile", + "prolog", + "properties", + "proto", + "protobuf", + "ps", + "ps1", + "puppet", + "py", + "pycon", + "python-repl", + "python", + "qml", + "r", + "razor-cshtml", + "razor", + "rb", + "re", + "reasonml", + "rebol", + "red-system", + "red", + "redbol", + "rf", + "rib", + "robot", + "rpm-spec", + "rpm-specfile", + "rpm", + "rs", + "rsl", + "rss", + "ruby", + "ruleslanguage", + "rust", + "sas", + "SAS", + "sc", + "scad", + "scala", + "scheme", + "sci", + "scilab", + "scl", + "scss", + "sh", + "shell", + "shexc", + "smali", + "smalltalk", + "sml", + "sol", + "solidity", + "spec", + "specfile", + "sql", + "srt", + "ssa", + "st", + "stan", + "stanfuncs", + "stata", + "step", + "stp", + "structured-text", + "styl", + "stylus", + "subunit", + "supercollider", + "svelte", + "svg", + "swift", + "tao", + "tap", + "tcl", + "terraform", + "tex", + "text", + "tf", + "thor", + "thrift", + "tk", + "toml", + "tp", + "ts", + "tsql", + "tsx", + "ttml", + "twig", + "txt", + "typescript", + "unicorn-rails-log", + "v", + "vala", + "vb", + "vba", + "vbnet", + "vbs", + "vbscript", + "verilog", + "vhdl", + "vim", + "vtt", + "wl", + "x++", + "x86asm", + "xhtml", + "xjb", + "xl", + "xml", + "xpath", + "xq", + "xquery", + "xsd", + "xsl", + "xtlang", + "xtm", + "yaml", + "yml", + "zep", + "zephir", + "zone", + "zsh" +]) + module.exports.getPermissions = getPermissions module.exports.getDefaultPermissions = getDefaultPermissions module.exports.hasPermission = hasPermission @@ -194,3 +582,4 @@ module.exports.timestampToSnowflakeInexact = timestampToSnowflakeInexact module.exports.getPublicUrlForCdn = getPublicUrlForCdn module.exports.howOldUnbridgedMessage = howOldUnbridgedMessage module.exports.filterTo = filterTo +module.exports.supportedPlaintextPreviewExtensions = supportedPlaintextPreviewExtensions diff --git a/src/m2d/converters/event-to-message.js b/src/m2d/converters/event-to-message.js index af44c84..31caef0 100644 --- a/src/m2d/converters/event-to-message.js +++ b/src/m2d/converters/event-to-message.js @@ -894,7 +894,8 @@ async function eventToMessage(event, guild, channel, di) { let preNode if (node.nodeType === 3 && node.nodeValue.includes("```") && (preNode = nodeIsChildOf(node, ["PRE"]))) { if (preNode.firstChild?.nodeName === "CODE") { - const ext = preNode.firstChild.className.match(/language-(\S+)/)?.[1] || "txt" + let ext = preNode.firstChild.className.match(/language-(\S+)/)?.[1] + if (!dUtils.supportedPlaintextPreviewExtensions.has(ext)) ext = "txt" const filename = `inline_code.${ext}` // Build the replacement node const replacementCode = doc.createElement("code") diff --git a/src/m2d/converters/event-to-message.test.js b/src/m2d/converters/event-to-message.test.js index bc73df7..68d519a 100644 --- a/src/m2d/converters/event-to-message.test.js +++ b/src/m2d/converters/event-to-message.test.js @@ -1155,6 +1155,38 @@ test("event2message: code blocks are uploaded as attachments instead if they con ) }) +test("event2message: code blocks are uploaded as attachments instead if they contain incompatible backticks (use txt extension if discord does not recognise the language)", async t => { + t.deepEqual( + await eventToMessage({ + type: "m.room.message", + sender: "@cadence:cadence.moe", + content: { + msgtype: "m.text", + body: "wrong body", + format: "org.matrix.custom.html", + formatted_body: 'So if you run code like this
System.out.println("```");
it should print a markdown formatted code block' + }, + event_id: "$pGkWQuGVmrPNByrFELxhzI6MCBgJecr5I2J3z88Gc2s", + room_id: "!kLRqKKUQXcibIMtOpl:cadence.moe" + }), + { + ensureJoined: [], + messagesToDelete: [], + messagesToEdit: [], + messagesToSend: [{ + username: "cadence [they]", + content: "So if you run code like this `[inline_code.txt]` it should print a markdown formatted code block", + attachments: [{id: "0", filename: "inline_code.txt"}], + pendingFiles: [{name: "inline_code.txt", buffer: Buffer.from('System.out.println("```");')}], + avatar_url: undefined, + allowed_mentions: { + parse: ["users", "roles"] + } + }] + } + ) +}) + test("event2message: code blocks are uploaded as attachments instead if they contain incompatible backticks (default to txt file extension)", async t => { t.deepEqual( await eventToMessage({