| author | Stephen Paul Weber
<singpolyma@singpolyma.net> 2026-05-03 03:07:52 UTC |
| committer | Stephen Paul Weber
<singpolyma@singpolyma.net> 2026-05-03 03:07:52 UTC |
| parent | b93c05534c0b5c37df5daa4340f19fd126e1fc01 |
| borogove/ChatMessage.hx | +5 | -1 |
| borogove/Html.hx | +1 | -1 |
| borogove/XEP0393.hx | +5 | -2 |
| test/TestChatMessage.hx | +20 | -1 |
diff --git a/borogove/ChatMessage.hx b/borogove/ChatMessage.hx index 3433c2a..c84681a 100644 --- a/borogove/ChatMessage.hx +++ b/borogove/ChatMessage.hx @@ -395,7 +395,11 @@ class ChatMessage { if (payloads.find((p) -> p.attr.get("xmlns") == "urn:xmpp:styling:0" && p.name == "unstyled") == null) { return XEP0393.parse(body).map(s -> Element(s)); } else { - return body.split("\n").map(line -> Element(new Stanza("div").text(line))); + return body.split("\n\n").map(para -> { + final lines = para.split("\n").flatMap(line -> [CData(new TextNode(line)), Element(new Stanza("br"))]); + lines.pop(); + return Element(new Stanza("p").addChildNodes(lines)); + }); } } } diff --git a/borogove/Html.hx b/borogove/Html.hx index 70ce706..3ef6d0e 100644 --- a/borogove/Html.hx +++ b/borogove/Html.hx @@ -250,7 +250,7 @@ class Html { // Could use reduce, but we already have XEP0393.render around final body = new Stanza("body"); body.addChildNodes(xml); - return ~/\n$/.replace(XEP0393.render(body), ""); + return ~/\n(\n)?$/.replace(XEP0393.render(body), ""); } #if js diff --git a/borogove/XEP0393.hx b/borogove/XEP0393.hx index 0ba958f..61ec127 100644 --- a/borogove/XEP0393.hx +++ b/borogove/XEP0393.hx @@ -113,13 +113,17 @@ class XEP0393 { endsWithNewline = true; } + if (xhtml.name == "p") { + s.add("\n"); + } + if (xhtml.name == "pre") { s.add("```\n"); endsWithNewline = true; } if (xhtml.name == "blockquote") { - return ~/^/gm.replace(s.toString(), "> "); + return ~/^/gm.replace(s.toString(), "> ") + "\n"; } return s.toString(); @@ -261,7 +265,6 @@ class XEP0393 { return { block: new Stanza("blockquote").addChildren(parse(lines.join(""))), rest: styled.substr(end) }; } - public static function parsePreformatted(styled: UnicodeString) { final lines = []; var line = ""; diff --git a/test/TestChatMessage.hx b/test/TestChatMessage.hx index 620235a..cbb922a 100644 --- a/test/TestChatMessage.hx +++ b/test/TestChatMessage.hx @@ -9,6 +9,25 @@ import borogove.Message; @:access(borogove) class TestChatMessage extends utest.Test { public function testUnstyledBody() { + final stanza = new Stanza("message"); + stanza.attr.set("id", "test-id-1"); + stanza.attr.set("from", "alice@example.com"); + stanza.attr.set("to", "bob@example.com"); + stanza.attr.set("type", "chat"); + stanza.addChild(new Stanza("body").text("line 1\n\n*line 2*")); + stanza.addChild(new Stanza("unstyled", {xmlns: "urn:xmpp:styling:0"})); + + final msg = Message.fromStanza(stanza, JID.parse("bob@example.com")); + switch (msg.parsed) { + case ChatMessageStanza(m): + Assert.equals("<p>line 1</p><p>*line 2*</p>", m.body().toString()); + Assert.equals("line 1\n\n*line 2*", m.body().toPlainText()); + default: + Assert.fail("Expected ChatMessageStanza"); + } + } + + public function testUnstyledBodyLineBreak() { final stanza = new Stanza("message"); stanza.attr.set("id", "test-id-1"); stanza.attr.set("from", "alice@example.com"); @@ -20,7 +39,7 @@ class TestChatMessage extends utest.Test { final msg = Message.fromStanza(stanza, JID.parse("bob@example.com")); switch (msg.parsed) { case ChatMessageStanza(m): - Assert.equals("<div>line 1</div><div>*line 2*</div>", m.body().toString()); + Assert.equals("<p>line 1<br />*line 2*</p>", m.body().toString()); Assert.equals("line 1\n*line 2*", m.body().toPlainText()); default: Assert.fail("Expected ChatMessageStanza");