mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	Previously we use `hash_util_encode` to encode channel and topic names to be URL compatible. This uses the more capable `encode_hash_component` from the recently added `topic_link_utils.py` module. It also moves the function to `url_encoding.py`
		
			
				
	
	
		
			89 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			89 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# Keep this synchronized with web/src/topic_link_util.ts
 | 
						|
 | 
						|
import re
 | 
						|
 | 
						|
from zerver.lib.url_encoding import encode_channel, encode_hash_component
 | 
						|
from zerver.models.messages import Message
 | 
						|
 | 
						|
invalid_stream_topic_regex = re.compile(r"[`>*&\[\]]|(\$\$)")
 | 
						|
 | 
						|
 | 
						|
def will_produce_broken_stream_topic_link(word: str) -> bool:
 | 
						|
    return bool(invalid_stream_topic_regex.search(word))
 | 
						|
 | 
						|
 | 
						|
escape_mapping = {
 | 
						|
    "`": "`",
 | 
						|
    ">": ">",
 | 
						|
    "*": "*",
 | 
						|
    "&": "&",
 | 
						|
    "$$": "$$",
 | 
						|
    "[": "[",
 | 
						|
    "]": "]",
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
def escape_invalid_stream_topic_characters(text: str) -> str:
 | 
						|
    return re.sub(
 | 
						|
        invalid_stream_topic_regex,
 | 
						|
        lambda match: escape_mapping.get(match.group(0), match.group(0)),
 | 
						|
        text,
 | 
						|
    )
 | 
						|
 | 
						|
 | 
						|
def get_fallback_markdown_link(
 | 
						|
    stream_id: int, stream_name: str, topic_name: str | None = None, message_id: int | None = None
 | 
						|
) -> str:
 | 
						|
    """
 | 
						|
    Helper that should only be called by other methods in this file.
 | 
						|
 | 
						|
    Generates the vanilla markdown link syntax for a stream/topic/message link, as
 | 
						|
    a fallback for cases where the nicer Zulip link syntax would not
 | 
						|
    render properly due to special characters in the channel or topic name.
 | 
						|
    """
 | 
						|
    escape = escape_invalid_stream_topic_characters
 | 
						|
    link = f"#narrow/channel/{encode_channel(stream_id, stream_name)}"
 | 
						|
    text = f"#{escape(stream_name)}"
 | 
						|
    if topic_name is not None:
 | 
						|
        link += f"/topic/{encode_hash_component(topic_name)}"
 | 
						|
        if topic_name == "":
 | 
						|
            topic_name = Message.EMPTY_TOPIC_FALLBACK_NAME
 | 
						|
        text += f" > {escape(topic_name)}"
 | 
						|
 | 
						|
    if message_id is not None:
 | 
						|
        link += f"/near/{message_id}"
 | 
						|
        text += " @ 💬"
 | 
						|
 | 
						|
    return f"[{text}]({link})"
 | 
						|
 | 
						|
 | 
						|
def get_message_link_syntax(
 | 
						|
    stream_id: int, stream_name: str, topic_name: str, message_id: int
 | 
						|
) -> str:
 | 
						|
    # If the stream/topic name is such that it will
 | 
						|
    # generate an invalid #**stream>topic@message_id** syntax,
 | 
						|
    # we revert to generating the normal markdown syntax for a link.
 | 
						|
    if will_produce_broken_stream_topic_link(topic_name) or will_produce_broken_stream_topic_link(
 | 
						|
        stream_name
 | 
						|
    ):
 | 
						|
        return get_fallback_markdown_link(stream_id, stream_name, topic_name, message_id)
 | 
						|
    return f"#**{stream_name}>{topic_name}@{message_id}**"
 | 
						|
 | 
						|
 | 
						|
def get_stream_topic_link_syntax(stream_id: int, stream_name: str, topic_name: str) -> str:
 | 
						|
    # If the stream/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) or will_produce_broken_stream_topic_link(
 | 
						|
        stream_name
 | 
						|
    ):
 | 
						|
        return get_fallback_markdown_link(stream_id, stream_name, topic_name)
 | 
						|
    return f"#**{stream_name}>{topic_name}**"
 | 
						|
 | 
						|
 | 
						|
def get_stream_link_syntax(stream_id: int, stream_name: str) -> str:
 | 
						|
    # If the stream name is such that it will generate an invalid #**stream** syntax,
 | 
						|
    # we revert to generating the normal markdown syntax for a link.
 | 
						|
    if will_produce_broken_stream_topic_link(stream_name):
 | 
						|
        return get_fallback_markdown_link(stream_id, stream_name)
 | 
						|
    return f"#**{stream_name}**"
 |