mirror of https://github.com/zulip/zulip.git
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:
parent
fad7a3f4b4
commit
5a24dad5f8
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)})`;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue