| author | Stephen Paul Weber
<singpolyma@singpolyma.net> 2026-04-11 03:44:09 UTC |
| committer | Stephen Paul Weber
<singpolyma@singpolyma.net> 2026-04-11 03:59:23 UTC |
| parent | 12360ae68615dd11bb2f18c970c8a7b4eac90ba0 |
| borogove/ChatMessage.hx | +5 | -1 |
| borogove/XEP0393.hx | +2 | -1 |
| test/TestAll.hx | +1 | -0 |
| test/TestChatMessage.hx | +47 | -0 |
| test/TestXEP0393.hx | +7 | -18 |
diff --git a/borogove/ChatMessage.hx b/borogove/ChatMessage.hx index affe8c9..e5a15f5 100644 --- a/borogove/ChatMessage.hx +++ b/borogove/ChatMessage.hx @@ -392,7 +392,11 @@ class ChatMessage { codepoints.splice(fallback.start, (fallback.end - fallback.start)); } final body = codepoints.join(""); - return payloads.find((p) -> p.attr.get("xmlns") == "urn:xmpp:styling:0" && p.name == "unstyled") == null ? XEP0393.parse(body).map(s -> Element(s)) : [CData(new TextNode(body))]; + 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))); + } } } diff --git a/borogove/XEP0393.hx b/borogove/XEP0393.hx index a66f382..4ad6c7a 100644 --- a/borogove/XEP0393.hx +++ b/borogove/XEP0393.hx @@ -186,8 +186,9 @@ class XEP0393 { var end = 0; final styledLength = styled.length; while (end < styledLength && styled.charAt(end) != "\n") end++; + final lineEnd = end; if (end < styledLength && styled.charAt(end) == "\n") end++; - return { block: new Stanza("div").addChildNodes(parseSpans(styled.substr(0, end))), rest: styled.substr(end) }; + return { block: new Stanza("div").addChildNodes(parseSpans(styled.substr(0, lineEnd))), rest: styled.substr(end) }; } } diff --git a/test/TestAll.hx b/test/TestAll.hx index 535cc9b..6eb702e 100644 --- a/test/TestAll.hx +++ b/test/TestAll.hx @@ -6,6 +6,7 @@ import utest.ui.Report; class TestAll { public static function main() { utest.UTest.run([ + new TestChatMessage(), new TestSessionDescription(), new TestChatMessageBuilder(), new TestStanza(), diff --git a/test/TestChatMessage.hx b/test/TestChatMessage.hx new file mode 100644 index 0000000..bd6238f --- /dev/null +++ b/test/TestChatMessage.hx @@ -0,0 +1,47 @@ +package test; + +import utest.Assert; +import borogove.Stanza; +import borogove.ChatMessage; +import borogove.JID; +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*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("<div>line 1</div><div>*line 2*</div>", m.body().toString()); + Assert.equals("line 1\n*line 2*", m.body().toPlainText()); + default: + Assert.fail("Expected ChatMessageStanza"); + } + } + + public function testStyledBody() { + 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*line 2*")); + + final msg = Message.fromStanza(stanza, JID.parse("bob@example.com")); + switch (msg.parsed) { + case ChatMessageStanza(m): + Assert.equals("<div>line 1</div><div><strong>line 2</strong></div>", m.body().toString()); + Assert.equals("line 1\n*line 2*", m.body().toPlainText()); + default: + Assert.fail("Expected ChatMessageStanza"); + } + } +} diff --git a/test/TestXEP0393.hx b/test/TestXEP0393.hx index 757988b..6698278 100644 --- a/test/TestXEP0393.hx +++ b/test/TestXEP0393.hx @@ -13,9 +13,7 @@ class TestXEP0393 extends utest.Test { public function testSpansDoNotEscapeBlocks() { Assert.equals( - "<div>There are three blocks in this body, one per line, -</div><div>but there is no *formatting -</div><div>as spans* may not escape blocks.</div>", + "<div>There are three blocks in this body, one per line,</div><div>but there is no *formatting</div><div>as spans* may not escape blocks.</div>", toHtml("There are three blocks in this body, one per line, but there is no *formatting as spans* may not escape blocks.") @@ -25,8 +23,7 @@ as spans* may not escape blocks.") public function testPreformattedBlock() { Assert.equals( "<pre>(println \"Hello, world!\") -</pre><div> -</div><div>This should show up as monospace, preformatted text ⤴</div>", +</pre><div/><div>This should show up as monospace, preformatted text ⤴</div>", toHtml("```ignored (println \"Hello, world!\") ``` @@ -38,9 +35,7 @@ This should show up as monospace, preformatted text ⤴") public function testPreformattedBlockUnterminated() { Assert.equals( "<blockquote><pre>(println \"Hello, world!\") -</pre></blockquote><div> -</div><div>The entire blockquote is a preformatted text block, but this line -</div><div>is plaintext!</div>", +</pre></blockquote><div/><div>The entire blockquote is a preformatted text block, but this line</div><div>is plaintext!</div>", toHtml("> ```ignored > (println \"Hello, world!\") @@ -51,9 +46,7 @@ is plaintext!") public function testQuotation() { Assert.equals( - "<blockquote><div>That that is, is. -</div></blockquote><div> -</div><div>Said the old hermit of Prague.</div>", + "<blockquote><div>That that is, is.</div></blockquote><div/><div>Said the old hermit of Prague.</div>", toHtml("> That that is, is. Said the old hermit of Prague.") @@ -62,10 +55,7 @@ Said the old hermit of Prague.") public function testNestedQuotation() { Assert.equals( - "<blockquote><blockquote><div>That that is, is. -</div></blockquote><div>Said the old hermit of Prague. -</div></blockquote><div> -</div><div>Who?</div>", + "<blockquote><blockquote><div>That that is, is.</div></blockquote><div>Said the old hermit of Prague.</div></blockquote><div/><div>Who?</div>", toHtml(">> That that is, is. > Said the old hermit of Prague. @@ -158,7 +148,7 @@ Who?") public function testNotStrong3() { Assert.equals( - "<div>*not \n</div><div> strong</div>", + "<div>*not </div><div> strong</div>", toHtml("*not \n strong") ); } @@ -210,8 +200,7 @@ Who?") public function testAutolink() { Assert.equals( - "<blockquote><div><a href=\"https://example.com\">example.com</a> -</div></blockquote>", + "<blockquote><div><a href=\"https://example.com\">example.com</a></div></blockquote>", toHtml("> example.com") ); }