copy_and_paste: Transform message links to pretty syntax.

Similar to #29302, we transform zulip message links to
a pretty syntax and in case there are some problematic
characters (#30071), we generate a fallback markdown link.

Fixes #31920
This commit is contained in:
Kislay Udbhav Verma 2024-10-27 19:13:14 +05:30 committed by Tim Abbott
parent fad7a3f4b4
commit 5a24dad5f8
4 changed files with 47 additions and 10 deletions

View File

@ -673,20 +673,33 @@ export function try_stream_topic_syntax_text(text: string): string | null {
assert(stream !== undefined);
const stream_name = stream.name;
if (topic_link_util.will_produce_broken_stream_topic_link(stream_name)) {
return topic_link_util.get_fallback_markdown_link(stream_name, stream_topic.topic_name);
return topic_link_util.get_fallback_markdown_link(
stream_name,
stream_topic.topic_name,
stream_topic.message_id,
);
}
if (
stream_topic.topic_name !== undefined &&
topic_link_util.will_produce_broken_stream_topic_link(stream_topic.topic_name)
) {
return topic_link_util.get_fallback_markdown_link(stream_name, stream_topic.topic_name);
return topic_link_util.get_fallback_markdown_link(
stream_name,
stream_topic.topic_name,
stream_topic.message_id,
);
}
let syntax_text = "#**" + stream_name;
if (stream_topic.topic_name) {
syntax_text += ">" + stream_topic.topic_name;
}
if (stream_topic.message_id !== undefined) {
syntax_text += "@" + stream_topic.message_id;
}
syntax_text += "**";
return syntax_text;
}

View File

@ -293,7 +293,7 @@ export function validate_group_settings_hash(hash: string): string {
export function decode_stream_topic_from_url(
url_str: string,
): {stream_id: number; topic_name?: string} | null {
): {stream_id: number; topic_name?: string; message_id?: string} | null {
try {
const url = new URL(url_str);
if (url.origin !== window.location.origin || !url.hash.startsWith("#narrow")) {
@ -303,9 +303,8 @@ export function decode_stream_topic_from_url(
if (terms === undefined) {
return null;
}
if (terms.length > 2) {
if (terms.length > 3) {
// The link should only contain stream and topic,
// near/ links are not transformed.
return null;
}
// This check is important as a malformed url
@ -324,7 +323,13 @@ export function decode_stream_topic_from_url(
if (terms[1]?.operator !== "topic") {
return null;
}
if (terms.length === 2) {
return {stream_id, topic_name: terms[1].operand};
}
if (terms[2]?.operator !== "near") {
return null;
}
return {stream_id, topic_name: terms[1].operand, message_id: terms[2].operand};
} catch {
return null;
}

View File

@ -37,13 +37,25 @@ export function html_escape_markdown_syntax_characters(text: string): string {
return text.replaceAll(invalid_stream_topic_regex, escape_invalid_stream_topic_characters);
}
export function get_fallback_markdown_link(stream_name: string, topic_name?: string): string {
export function get_fallback_markdown_link(
stream_name: string,
topic_name?: string,
message_id?: string,
): string {
const stream = stream_data.get_sub(stream_name);
const stream_id = stream?.stream_id;
assert(stream_id !== undefined);
const escape = html_escape_markdown_syntax_characters;
if (topic_name !== undefined) {
return `[#${escape(stream_name)} > ${escape(topic_name)}](${internal_url.by_stream_topic_url(stream_id, topic_name, () => stream_name)})`;
const stream_topic_url = internal_url.by_stream_topic_url(
stream_id,
topic_name,
() => stream_name,
);
if (message_id !== undefined) {
return `[#${escape(stream_name)} > ${escape(topic_name)} @ 💬](${stream_topic_url}/near/${message_id})`;
}
return `[#${escape(stream_name)} > ${escape(topic_name)}](${stream_topic_url})`;
}
return `[#${escape(stream_name)}](${internal_url.by_stream_url(stream_id, () => stream_name)})`;
}

View File

@ -33,17 +33,20 @@ run_test("try_stream_topic_syntax_text", () => {
],
["http://different.origin.com/#narrow/channel/4-Rome/topic/old.20FAILED.20EXPORT"],
[
"http://zulip.zulipdev.com/#narrow/channel/4-Rome/topic/old.20FAILED.20EXPORT/near/100",
"#**Rome>old FAILED EXPORT@100**",
],
// malformed urls
["http://zulip.zulipdev.com/narrow/channel/4-Rome/topic/old.20FAILED.20EXPORT"],
["http://zulip.zulipdev.com/#not_narrow/channel/4-Rome/topic/old.20FAILED.20EXPORT"],
["http://zulip.zulipdev.com/#narrow/not_stream/4-Rome/topic/old.20FAILED.20EXPORT"],
["http://zulip.zulipdev.com/#narrow/channel/4-Rome/not_topic/old.20FAILED.20EXPORT"],
["http://zulip.zulipdev.com/#narrow/channel/4-Rome/topic/old.20FAILED.20EXPORT/near/100"],
["http://zulip.zulipdev.com/#narrow/channel/4-Rome/", "#**Rome**"],
["http://zulip.zulipdev.com/#narrow/channel/4-Rome/topic"],
["http://zulip.zulipdev.com/#narrow/topic/cheese"],
["http://zulip.zulipdev.com/#narrow/topic/pizza/stream/Rome"],
["http://zulip.zulipdev.com/#narrow/channel/4-Rome/topic/old.20FAILED.20EXPORT/near/"],
// When a url containing characters which are known to produce broken
// #**stream>topic** urls is pasted, a normal markdown link syntax is produced.
@ -67,6 +70,10 @@ run_test("try_stream_topic_syntax_text", () => {
"http://zulip.zulipdev.com/#narrow/stream/5-Romeo.60s-lair/topic/normal",
"[#Romeo`s lair > normal](#narrow/channel/5-Romeo.60s-lair/topic/normal)",
],
[
"http://zulip.zulipdev.com/#narrow/stream/4-Rome/topic/100.25.20profits.60/near/20",
"[#Rome > 100% profits` @ 💬](#narrow/channel/4-Rome/topic/100.25.20profits.60/near/20)",
],
];
for (const test_case of test_cases) {