markdown: Support message link syntax in local echo.

This is a followup to #31965 where we added
support for a new syntax for message links.
The frontend markdown processor didn't local
echo the syntax properly, resulting in a
rendering glitch in the messages.
This commit is contained in:
Kislay Verma
2024-12-03 20:33:16 +05:30
committed by Tim Abbott
parent c56cc14539
commit dfc1ea785f
3 changed files with 71 additions and 0 deletions

View File

@@ -647,6 +647,33 @@ function handleStreamTopic({
)}" href="/${_.escape(href)}">${_.escape(text)}</a>`; )}" href="/${_.escape(href)}">${_.escape(text)}</a>`;
} }
function handleStreamTopicMessage({
stream_name,
topic,
message_id,
get_stream_by_name,
stream_topic_hash,
}: {
stream_name: string;
topic: string;
message_id: number;
get_stream_by_name: (stream_name: string) =>
| {
stream_id: number;
name: string;
}
| undefined;
stream_topic_hash: (stream_id: number, topic: string) => string;
}): string | undefined {
const stream = get_stream_by_name(stream_name);
if (stream === undefined || !topic) {
return undefined;
}
const href = stream_topic_hash(stream.stream_id, topic) + "/near/" + message_id;
const text = `#${stream.name} > ${topic} @ 💬`;
return `<a class="message-link" href="/${_.escape(href)}">${_.escape(text)}</a>`;
}
function handleTex(tex: string, fullmatch: string): string { function handleTex(tex: string, fullmatch: string): string {
try { try {
return katex.renderToString(tex); return katex.renderToString(tex);
@@ -755,6 +782,20 @@ export function parse({
}); });
} }
function streamTopicMessageHandler(
stream_name: string,
topic: string,
message_id: number,
): string | undefined {
return handleStreamTopicMessage({
stream_name,
topic,
message_id,
get_stream_by_name: helper_config.get_stream_by_name,
stream_topic_hash: helper_config.stream_topic_hash,
});
}
function emojiHandler(emoji_name: string): string { function emojiHandler(emoji_name: string): string {
return handleEmoji({ return handleEmoji({
emoji_name, emoji_name,
@@ -782,6 +823,7 @@ export function parse({
unicodeEmojiHandler, unicodeEmojiHandler,
streamHandler, streamHandler,
streamTopicHandler, streamTopicHandler,
streamTopicMessageHandler,
texHandler: handleTex, texHandler: handleTex,
timestampHandler: handleTimestamp, timestampHandler: handleTimestamp,
gfm: true, gfm: true,

View File

@@ -420,6 +420,15 @@ test("marked", ({override}) => {
input: "This is not a #**Denmark>** stream_topic link", input: "This is not a #**Denmark>** stream_topic link",
expected: "<p>This is not a #**Denmark&gt;** stream_topic link</p>", expected: "<p>This is not a #**Denmark&gt;** stream_topic link</p>",
}, },
{
input: "Look at #**Denmark>message_link@100**",
expected:
'<p>Look at <a class="message-link" href="/#narrow/channel/1-Denmark/topic/message_link/near/100">#Denmark &gt; message_link @ 💬</a></p>',
},
{
input: "Look at #**Unknown>message_link@100**",
expected: "<p>Look at #**Unknown&gt;message_link@100**</p>",
},
{ {
input: "mmm...:burrito:s", input: "mmm...:burrito:s",
expected: expected:

View File

@@ -545,6 +545,7 @@ inline.zulip = merge({}, inline.breaks, {
unicodeemoji: possible_emoji_regex, unicodeemoji: possible_emoji_regex,
usermention: /^@(_?)(?:\*\*([^\*]+)\*\*)/, // Match potentially multi-word string between @** ** usermention: /^@(_?)(?:\*\*([^\*]+)\*\*)/, // Match potentially multi-word string between @** **
groupmention: /^@(_?)(?:\*([^\*]+)\*)/, // Match multi-word string between @* * groupmention: /^@(_?)(?:\*([^\*]+)\*)/, // Match multi-word string between @* *
stream_topic_message: /^#\*\*([^\*>]+)>([^\*]+)@(\d+)\*\*/,
stream_topic: /^#\*\*([^\*>]+)>([^\*]+)\*\*/, stream_topic: /^#\*\*([^\*>]+)>([^\*]+)\*\*/,
stream: /^#\*\*([^\*]+)\*\*/, stream: /^#\*\*([^\*]+)\*\*/,
tex: /^(\$\$([^\n_$](\\\$|[^\n$])*)\$\$(?!\$))\B/, tex: /^(\$\$([^\n_$](\\\$|[^\n$])*)\$\$(?!\$))\B/,
@@ -754,6 +755,13 @@ InlineLexer.prototype.output = function(src) {
continue; continue;
} }
// stream_topic_message (Zulip)
if (cap = this.rules.stream_topic_message.exec(src)) {
src = src.substring(cap[0].length);
out += this.stream_topic_message(unescape(cap[1]), unescape(cap[2]), unescape(cap[3]), cap[0]);
continue;
}
// stream_topic (Zulip) // stream_topic (Zulip)
if (cap = this.rules.stream_topic.exec(src)) { if (cap = this.rules.stream_topic.exec(src)) {
src = src.substring(cap[0].length); src = src.substring(cap[0].length);
@@ -950,6 +958,18 @@ InlineLexer.prototype.stream_topic = function (streamName, topic, orig) {
return orig; return orig;
}; };
InlineLexer.prototype.stream_topic_message = function (streamName, topic, message_id, orig) {
orig = escape(orig);
if (typeof this.options.streamTopicMessageHandler !== 'function')
return orig;
var handled = this.options.streamTopicMessageHandler(streamName, topic, message_id);
if (handled !== undefined) {
return handled;
}
return orig;
};
/** /**
* Smartypants Transformations * Smartypants Transformations
*/ */