2024-06-10 09:02:16 +02:00
|
|
|
import assert from "minimalistic-assert";
|
|
|
|
|
|
|
|
import * as internal_url from "../shared/src/internal_url";
|
|
|
|
|
|
|
|
import * as stream_data from "./stream_data";
|
|
|
|
|
2024-10-19 18:23:56 +02:00
|
|
|
const invalid_stream_topic_regex = /[`>*&]|(\$\$)/g;
|
2024-06-10 09:02:16 +02:00
|
|
|
|
|
|
|
export function will_produce_broken_stream_topic_link(word: string): boolean {
|
|
|
|
return invalid_stream_topic_regex.test(word);
|
|
|
|
}
|
|
|
|
|
|
|
|
function get_stream_name_from_topic_link_syntax(syntax: string): string {
|
|
|
|
const start = syntax.indexOf("#**");
|
|
|
|
const end = syntax.lastIndexOf(">");
|
|
|
|
return syntax.slice(start + 3, end);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function escape_invalid_stream_topic_characters(text: string): string {
|
|
|
|
switch (text) {
|
|
|
|
case "`":
|
2024-10-19 10:04:56 +02:00
|
|
|
return "`";
|
2024-06-10 09:02:16 +02:00
|
|
|
case ">":
|
|
|
|
return ">";
|
|
|
|
case "*":
|
|
|
|
return "*";
|
2024-10-19 18:23:56 +02:00
|
|
|
case "&":
|
|
|
|
return "&";
|
2024-06-10 09:02:16 +02:00
|
|
|
case "$$":
|
|
|
|
return "$$";
|
|
|
|
default:
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
|
|
|
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)})`;
|
|
|
|
}
|
|
|
|
return `[#${escape(stream_name)}](${internal_url.by_stream_url(stream_id, () => stream_name)})`;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function get_stream_topic_link_syntax(
|
|
|
|
typed_syntax_text: string,
|
|
|
|
topic_name: string,
|
|
|
|
): string {
|
|
|
|
const stream_name = get_stream_name_from_topic_link_syntax(typed_syntax_text);
|
|
|
|
// If the topic name is such that it will generate an invalid #**stream>topic** syntax,
|
|
|
|
// we revert to generating the normal markdown syntax for a link.
|
|
|
|
if (
|
|
|
|
will_produce_broken_stream_topic_link(topic_name) ||
|
|
|
|
will_produce_broken_stream_topic_link(stream_name)
|
|
|
|
) {
|
|
|
|
return get_fallback_markdown_link(stream_name, topic_name);
|
|
|
|
}
|
|
|
|
return `#**${stream_name}>${topic_name}**`;
|
|
|
|
}
|