Fix more edge-case embed formatting

This commit is contained in:
Cadence Ember 2023-10-28 00:24:42 +13:00
parent 762e48230c
commit afbbe0da3d
12 changed files with 428 additions and 127 deletions

View file

@ -40,6 +40,7 @@ function encodeEmoji(input, shortcode) {
"%E2%AD%90", // ⭐
"%F0%9F%90%88", // 🐈
"%E2%9D%93", // ❓
"%F0%9F%8F%86", // 🏆️
]
discordPreferredEncoding =

View file

@ -110,6 +110,24 @@ turndownService.addRule("inlineLink", {
}
})
turndownService.addRule("listItem", {
filter: "li",
replacement: function (content, node, options) {
content = content
.replace(/^\n+/, "") // remove leading newlines
.replace(/\n+$/, "\n") // replace trailing newlines with just a single one
.replace(/\n/gm, "\n ") // indent
var prefix = options.bulletListMarker + " "
var parent = node.parentNode
if (parent.nodeName === "OL") {
var start = parent.getAttribute("start")
var index = Array.prototype.indexOf.call(parent.children, node)
prefix = (start ? Number(start) + index : index + 1) + ". "
}
return prefix + content + (node.nextSibling && !/\n$/.test(content) ? "\n" : "")
}
})
/** @type {string[]} SPRITE SHEET EMOJIS FEATURE: mxc urls for the currently processing message */
let endOfMessageEmojis = []
turndownService.addRule("emoji", {

View file

@ -368,7 +368,7 @@ test("event2message: lists are bridged correctly", async t => {
messagesToEdit: [],
messagesToSend: [{
username: "cadence [they]",
content: "* line one\n* line two\n* line three\n * nested one\n * nested two\n* line four",
content: "* line one\n* line two\n* line three\n * nested one\n * nested two\n* line four",
avatar_url: undefined
}]
}
@ -498,6 +498,47 @@ test("event2message: quotes have an appropriate amount of whitespace", async t =
)
})
test("event2message: lists have appropriate line breaks", async t => {
t.deepEqual(
await eventToMessage({
content: {
body: 'i am not certain what you mean by "already exists with as discord". my goals are\n' +
'* bridgeing specific channels with existing matrix rooms\n' +
' * optionally maybe entire "servers"\n' +
'* offering the bridge as a public service ',
format: 'org.matrix.custom.html',
formatted_body: '<p>i am not certain what you mean by "already exists with as discord". my goals are</p>\n' +
'<ul>\n' +
'<li>bridgeing specific channels with existing matrix rooms\n' +
'<ul>\n' +
'<li>optionally maybe entire "servers"</li>\n' +
'</ul>\n' +
'</li>\n' +
'<li>offering the bridge as a public service</li>\n' +
'</ul>\n',
'm.mentions': {},
msgtype: 'm.text'
},
room_id: '!cBxtVRxDlZvSVhJXVK:cadence.moe',
sender: '@Milan:tchncs.de',
type: 'm.room.message',
}, {}, {
api: {
getStateEvent: async () => ({displayname: "Milan"})
}
}),
{
messagesToDelete: [],
messagesToEdit: [],
messagesToSend: [{
username: "Milan",
content: `i am not certain what you mean by "already exists with as discord". my goals are\n\n* bridgeing specific channels with existing matrix rooms\n * optionally maybe entire "servers"\n* offering the bridge as a public service`,
avatar_url: undefined
}]
}
)
})
test("event2message: m.emote plaintext works", async t => {
t.deepEqual(
await eventToMessage({

View file

@ -16,6 +16,7 @@ const BLOCK_ELEMENTS = [
"NOSCRIPT", "OL", "OUTPUT", "P", "PRE", "SECTION", "SUMMARY", "TABLE", "TBODY", "TD",
"TFOOT", "TH", "THEAD", "TR", "UL"
]
const NEWLINE_ELEMENTS = BLOCK_ELEMENTS.concat(["BR"])
/**
* Determine whether an event is the bridged representation of a discord message.
@ -63,7 +64,71 @@ function getEventIDHash(eventID) {
return signedHash
}
class MatrixStringBuilder {
constructor() {
this.body = ""
this.formattedBody = ""
}
/**
* @param {string} body
* @param {string} formattedBody
* @param {any} [condition]
*/
add(body, formattedBody, condition = true) {
if (condition) {
if (formattedBody == undefined) formattedBody = body
this.body += body
this.formattedBody += formattedBody
}
return this
}
/**
* @param {string} body
* @param {string} [formattedBody]
* @param {any} [condition]
*/
addLine(body, formattedBody, condition = true) {
if (condition) {
if (formattedBody == undefined) formattedBody = body
if (this.body.length && this.body.slice(-1) !== "\n") this.body += "\n"
this.body += body
const match = this.formattedBody.match(/<\/?([a-zA-Z]+[a-zA-Z0-9]*)[^>]*>\s*$/)
if (this.formattedBody.length && (!match || !NEWLINE_ELEMENTS.includes(match[1].toUpperCase()))) this.formattedBody += "<br>"
this.formattedBody += formattedBody
}
return this
}
/**
* @param {string} body
* @param {string} [formattedBody]
* @param {any} [condition]
*/
addParagraph(body, formattedBody, condition = true) {
if (condition) {
if (formattedBody == undefined) formattedBody = body
if (this.body.length && this.body.slice(-1) !== "\n") this.body += "\n\n"
this.body += body
formattedBody = `<p>${formattedBody}</p>`
this.formattedBody += formattedBody
}
return this
}
get() {
return {
msgtype: "m.text",
body: this.body,
format: "org.matrix.custom.html",
formatted_body: this.formattedBody
}
}
}
module.exports.BLOCK_ELEMENTS = BLOCK_ELEMENTS
module.exports.eventSenderIsFromDiscord = eventSenderIsFromDiscord
module.exports.getPublicUrlForMxc = getPublicUrlForMxc
module.exports.getEventIDHash = getEventIDHash
module.exports.MatrixStringBuilder = MatrixStringBuilder