mirror of https://github.com/vector-im/riot-web
				
				
				
			Handle newlines in user pills (#11166)
* Handle newlines in user pills Fixes: vector-im/element-web#10994 * Fix typo in comment Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> * Refactor link generation for better readability * Use `<br>` instead of `<br/>` * Fix copy/paste error --------- Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>pull/28788/head^2
							parent
							
								
									3f20675b93
								
							
						
					
					
						commit
						d7677c7e21
					
				|  | @ -22,7 +22,7 @@ import { logger } from "matrix-js-sdk/src/logger"; | |||
| 
 | ||||
| import { linkify } from "./linkify-matrix"; | ||||
| 
 | ||||
| const ALLOWED_HTML_TAGS = ["sub", "sup", "del", "u"]; | ||||
| const ALLOWED_HTML_TAGS = ["sub", "sup", "del", "u", "br", "br/"]; | ||||
| 
 | ||||
| // These types of node are definitely text
 | ||||
| const TEXT_NODES = ["text", "softbreak", "linebreak", "paragraph", "document"]; | ||||
|  | @ -36,8 +36,8 @@ function isAllowedHtmlTag(node: commonmark.Node): boolean { | |||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     // Regex won't work for tags with attrs, but we only
 | ||||
|     // allow <del> anyway.
 | ||||
|     // Regex won't work for tags with attrs, but the tags we allow
 | ||||
|     // shouldn't really have any anyway.
 | ||||
|     const matches = /^<\/?(.*)>$/.exec(node.literal); | ||||
|     if (matches && matches.length == 2) { | ||||
|         const tag = matches[1]; | ||||
|  |  | |||
|  | @ -36,20 +36,20 @@ export function mdSerialize(model: EditorModel): string { | |||
|             case Type.PillCandidate: | ||||
|             case Type.AtRoomPill: | ||||
|                 return html + part.text; | ||||
|             case Type.RoomPill: | ||||
|             case Type.RoomPill: { | ||||
|                 const url = makeGenericPermalink(part.resourceId); | ||||
|                 // Escape square brackets and backslashes
 | ||||
|                 // Here we use the resourceId for compatibility with non-rich text clients
 | ||||
|                 // See https://github.com/vector-im/element-web/issues/16660
 | ||||
|                 return ( | ||||
|                     html + | ||||
|                     `[${part.resourceId.replace(/[[\\\]]/g, (c) => "\\" + c)}](${makeGenericPermalink( | ||||
|                         part.resourceId, | ||||
|                     )})` | ||||
|                 ); | ||||
|             case Type.UserPill: | ||||
|                 return ( | ||||
|                     html + | ||||
|                     `[${part.text.replace(/[[\\\]]/g, (c) => "\\" + c)}](${makeGenericPermalink(part.resourceId)})` | ||||
|                 ); | ||||
|                 const title = part.resourceId.replace(/[[\\\]]/g, (c) => "\\" + c); | ||||
|                 return html + `[${title}](${url})`; | ||||
|             } | ||||
|             case Type.UserPill: { | ||||
|                 const url = makeGenericPermalink(part.resourceId); | ||||
|                 // Escape square brackets and backslashes; convert newlines to HTML
 | ||||
|                 const title = part.text.replace(/[[\\\]]/g, (c) => "\\" + c).replace(/\n/g, "<br>"); | ||||
|                 return html + `[${title}](${url})`; | ||||
|             } | ||||
|         } | ||||
|     }, ""); | ||||
| } | ||||
|  |  | |||
|  | @ -183,6 +183,14 @@ describe("editor/deserialize", function () { | |||
|             expect(parts[1]).toStrictEqual({ type: "user-pill", text: "Alice]", resourceId: "@alice:hs.tld" }); | ||||
|             expect(parts[2]).toStrictEqual({ type: "plain", text: "!" }); | ||||
|         }); | ||||
|         it("user pill with displayname containing linebreak", function () { | ||||
|             const html = 'Hi <a href="https://matrix.to/#/@alice:hs.tld">Alice<br>123</a>!'; | ||||
|             const parts = normalize(parseEvent(htmlMessage(html), createPartCreator())); | ||||
|             expect(parts.length).toBe(3); | ||||
|             expect(parts[0]).toStrictEqual({ type: "plain", text: "Hi " }); | ||||
|             expect(parts[1]).toStrictEqual({ type: "user-pill", text: "Alice123", resourceId: "@alice:hs.tld" }); | ||||
|             expect(parts[2]).toStrictEqual({ type: "plain", text: "!" }); | ||||
|         }); | ||||
|         it("room pill", function () { | ||||
|             const html = 'Try <a href="https://matrix.to/#/#room:hs.tld">#room:hs.tld</a>?'; | ||||
|             const parts = normalize(parseEvent(htmlMessage(html), createPartCreator())); | ||||
|  |  | |||
|  | @ -63,6 +63,12 @@ describe("editor/serialize", function () { | |||
|             const html = htmlSerializeIfNeeded(model, {}); | ||||
|             expect(html).toBe('<a href="https://matrix.to/#/@user:server">Displayname]</a>'); | ||||
|         }); | ||||
|         it("displaynames containing a newline work", function () { | ||||
|             const pc = createPartCreator(); | ||||
|             const model = new EditorModel([pc.userPill("Display\nname", "@user:server")], pc); | ||||
|             const html = htmlSerializeIfNeeded(model, {}); | ||||
|             expect(html).toBe('<a href="https://matrix.to/#/@user:server">Display<br>name</a>'); | ||||
|         }); | ||||
|         it("escaped markdown should not retain backslashes", function () { | ||||
|             const pc = createPartCreator(); | ||||
|             const model = new EditorModel([pc.plain("\\*hello\\* world")], pc); | ||||
|  | @ -96,7 +102,6 @@ describe("editor/serialize", function () { | |||
|             const html = htmlSerializeIfNeeded(model, { useMarkdown: false }); | ||||
|             expect(html).toBe("\\*hello\\* world < hey world!"); | ||||
|         }); | ||||
| 
 | ||||
|         it("plaintext remains plaintext even when forcing html", function () { | ||||
|             const pc = createPartCreator(); | ||||
|             const model = new EditorModel([pc.plain("hello world")], pc); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Johannes Marbach
						Johannes Marbach