2018-09-15 06:17:04 +02:00
|
|
|
import re
|
2022-04-27 04:23:43 +02:00
|
|
|
from typing import Any, List, Match
|
2020-06-11 00:54:34 +02:00
|
|
|
|
2020-10-19 06:37:43 +02:00
|
|
|
from markdown import Markdown
|
|
|
|
from markdown.extensions import Extension
|
2018-09-15 06:17:04 +02:00
|
|
|
from markdown.preprocessors import Preprocessor
|
2023-10-12 19:43:45 +02:00
|
|
|
from typing_extensions import override
|
2018-09-15 06:17:04 +02:00
|
|
|
|
2022-06-26 02:35:20 +02:00
|
|
|
from zerver.lib.markdown.priorities import PREPROCESSOR_PRIORITES
|
2021-09-17 19:01:36 +02:00
|
|
|
|
2018-09-15 06:17:04 +02:00
|
|
|
# There is a lot of duplicated code between this file and
|
|
|
|
# help_settings_links.py. So if you're making a change here consider making
|
|
|
|
# it there as well.
|
|
|
|
|
2021-02-12 08:20:45 +01:00
|
|
|
REGEXP = re.compile(r"\{relative\|(?P<link_type>.*?)\|(?P<key>.*?)\}")
|
2018-09-15 06:17:04 +02:00
|
|
|
|
|
|
|
gear_info = {
|
|
|
|
# The pattern is key: [name, link]
|
|
|
|
# key is from REGEXP: `{relative|gear|key}`
|
|
|
|
# name is what the item is called in the gear menu: `Select **name**.`
|
|
|
|
# link is used for relative links: `Select [name](link).`
|
2023-11-17 17:53:41 +01:00
|
|
|
"stream-settings": ['<i class="fa fa-exchange"></i> Stream settings', "/#streams/subscribed"],
|
2023-07-25 15:41:30 +02:00
|
|
|
"settings": ['<i class="fa fa-wrench"></i> Personal Settings', "/#settings/profile"],
|
|
|
|
"organization-settings": [
|
|
|
|
'<i class="fa fa-bolt"></i> Organization settings',
|
|
|
|
"/#organization/organization-profile",
|
|
|
|
],
|
|
|
|
"integrations": ['<i class="fa fa-github"></i> Integrations', "/integrations/"],
|
|
|
|
"stats": ['<i class="fa fa-bar-chart"></i> Usage statistics', "/stats"],
|
|
|
|
"plans": ['<i class="fa fa-rocket"></i> Plans and pricing', "/plans/"],
|
|
|
|
"billing": ['<i class="fa fa-credit-card"></i> Billing', "/billing/"],
|
2022-04-12 12:22:04 +02:00
|
|
|
"about-zulip": ["About Zulip", "/#about-zulip"],
|
2018-09-15 06:17:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
gear_instructions = """
|
2021-08-17 10:08:33 +02:00
|
|
|
1. Click on the **gear** (<i class="fa fa-cog"></i>) icon in the upper
|
|
|
|
right corner of the web or desktop app.
|
2018-09-15 06:17:04 +02:00
|
|
|
|
2020-07-10 01:57:43 +02:00
|
|
|
1. Select {item}.
|
2018-09-15 06:17:04 +02:00
|
|
|
"""
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2018-09-15 06:17:04 +02:00
|
|
|
def gear_handle_match(key: str) -> str:
|
|
|
|
if relative_help_links:
|
2021-02-12 08:20:45 +01:00
|
|
|
item = f"[{gear_info[key][0]}]({gear_info[key][1]})"
|
2018-09-15 06:17:04 +02:00
|
|
|
else:
|
2021-02-12 08:20:45 +01:00
|
|
|
item = f"**{gear_info[key][0]}**"
|
2020-07-10 01:57:43 +02:00
|
|
|
return gear_instructions.format(item=item)
|
2018-09-15 06:17:04 +02:00
|
|
|
|
2018-09-16 04:29:56 +02:00
|
|
|
|
2023-10-26 03:56:57 +02:00
|
|
|
help_info = {
|
|
|
|
# The pattern is key: [name, link]
|
|
|
|
# key is from REGEXP: `{relative|help|key}`
|
|
|
|
# name is what the item is called in the help menu: `Select **name**.`
|
|
|
|
# link is used for relative links: `Select [name](link).`
|
|
|
|
"keyboard-shortcuts": [
|
|
|
|
'<i class="zulip-icon zulip-icon-keyboard"></i> Keyboard shortcuts',
|
|
|
|
"/#keyboard-shortcuts",
|
|
|
|
],
|
|
|
|
"message-formatting": [
|
|
|
|
'<i class="zulip-icon zulip-icon-edit"></i> Message formatting',
|
|
|
|
"/#message-formatting",
|
|
|
|
],
|
|
|
|
"search-filters": [
|
|
|
|
'<i class="zulip-icon zulip-icon-manage-search"></i> Search filters',
|
|
|
|
"/#search-operators",
|
|
|
|
],
|
|
|
|
}
|
|
|
|
|
|
|
|
help_instructions = """
|
|
|
|
1. Click on the **Help menu** (<i class="zulip-icon zulip-icon-help"></i>) icon
|
|
|
|
in the upper right corner of the app.
|
|
|
|
|
|
|
|
1. Select {item}.
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
def help_handle_match(key: str) -> str:
|
|
|
|
if relative_help_links:
|
|
|
|
item = f"[{help_info[key][0]}]({help_info[key][1]})"
|
|
|
|
else:
|
|
|
|
item = f"**{help_info[key][0]}**"
|
|
|
|
return help_instructions.format(item=item)
|
|
|
|
|
|
|
|
|
2018-09-16 04:29:56 +02:00
|
|
|
stream_info = {
|
2021-02-12 08:20:45 +01:00
|
|
|
"all": ["All streams", "/#streams/all"],
|
2022-03-28 17:54:29 +02:00
|
|
|
"subscribed": ["Subscribed streams", "/#streams/subscribed"],
|
2018-09-16 04:29:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
stream_instructions_no_link = """
|
2021-08-17 10:08:33 +02:00
|
|
|
1. Click on the **gear** (<i class="fa fa-cog"></i>) icon in the upper
|
|
|
|
right corner of the web or desktop app.
|
2018-09-16 04:29:56 +02:00
|
|
|
|
2023-11-17 17:53:41 +01:00
|
|
|
1. Click **Stream settings**.
|
2018-09-16 04:29:56 +02:00
|
|
|
"""
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2018-09-16 04:29:56 +02:00
|
|
|
def stream_handle_match(key: str) -> str:
|
|
|
|
if relative_help_links:
|
2020-06-10 06:41:04 +02:00
|
|
|
return f"1. Go to [{stream_info[key][0]}]({stream_info[key][1]})."
|
2021-02-12 08:20:45 +01:00
|
|
|
if key == "all":
|
2018-09-16 04:29:56 +02:00
|
|
|
return stream_instructions_no_link + "\n\n1. Click **All streams** in the upper left."
|
|
|
|
return stream_instructions_no_link
|
|
|
|
|
|
|
|
|
2023-06-26 20:38:34 +02:00
|
|
|
draft_instructions = """
|
|
|
|
1. Click on <i class="fa fa-pencil"></i> **Drafts** in the left sidebar.
|
|
|
|
"""
|
|
|
|
|
|
|
|
scheduled_instructions = """
|
|
|
|
1. Click on <i class="fa fa-calendar"></i> **Scheduled messages** in the left
|
|
|
|
sidebar. If you do not see this link, you have no scheduled messages.
|
|
|
|
"""
|
|
|
|
|
2023-07-21 02:10:05 +02:00
|
|
|
recent_instructions = """
|
|
|
|
1. Click on <i class="fa fa-clock-o"></i> **Recent conversations** in the left
|
2023-10-12 20:31:28 +02:00
|
|
|
sidebar, or use the <kbd>T</kbd> keyboard shortcut..
|
2023-07-21 02:10:05 +02:00
|
|
|
"""
|
|
|
|
|
2023-07-21 02:57:01 +02:00
|
|
|
all_instructions = """
|
|
|
|
1. Click on <i class="fa fa-align-left"></i> **All messages** in the left
|
2023-10-12 20:31:28 +02:00
|
|
|
sidebar, or use the <kbd>A</kbd> keyboard shortcut.
|
2023-07-21 02:57:01 +02:00
|
|
|
"""
|
|
|
|
|
2023-08-05 06:38:23 +02:00
|
|
|
starred_instructions = """
|
|
|
|
1. Click on <i class="fa fa-star"></i> **Starred messages** in the left
|
|
|
|
sidebar, or by [searching](/help/search-for-messages) for `is:starred`.
|
|
|
|
"""
|
|
|
|
|
2023-08-08 02:44:25 +02:00
|
|
|
direct_instructions = """
|
|
|
|
1. In the left sidebar, click the **All direct messages**
|
|
|
|
(<i class="fa fa-align-right"></i>) icon to the right of the
|
|
|
|
**Direct messages** label, or use the <kbd>Shift</kbd> + <kbd>P</kbd>
|
|
|
|
keyboard shortcut.
|
|
|
|
"""
|
|
|
|
|
2023-09-30 02:21:16 +02:00
|
|
|
inbox_instructions = """
|
|
|
|
1. Click on <i class="zulip-icon zulip-icon-inbox"></i> **Inbox** in the left
|
2023-10-12 20:31:28 +02:00
|
|
|
sidebar, or use the <kbd>Shift</kbd> + <kbd>I</kbd> keyboard shortcut.
|
2023-09-30 02:21:16 +02:00
|
|
|
"""
|
|
|
|
|
2023-06-26 20:38:34 +02:00
|
|
|
message_info = {
|
|
|
|
"drafts": ["Drafts", "/#drafts", draft_instructions],
|
|
|
|
"scheduled": ["Scheduled messages", "/#scheduled", scheduled_instructions],
|
2023-07-21 02:10:05 +02:00
|
|
|
"recent": ["Recent conversations", "/#recent", recent_instructions],
|
2023-07-21 02:57:01 +02:00
|
|
|
"all": ["All messages", "/#all_messages", all_instructions],
|
2023-08-05 06:38:23 +02:00
|
|
|
"starred": ["Starred messages", "/#narrow/is/starred", starred_instructions],
|
2023-08-08 02:44:25 +02:00
|
|
|
"direct": ["All direct messages", "/#narrow/is/dm", direct_instructions],
|
2023-09-30 02:21:16 +02:00
|
|
|
"inbox": ["Inbox", "/#inbox", inbox_instructions],
|
2023-06-26 20:38:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
def message_handle_match(key: str) -> str:
|
|
|
|
if relative_help_links:
|
|
|
|
return f"1. Go to [{message_info[key][0]}]({message_info[key][1]})."
|
|
|
|
else:
|
|
|
|
return message_info[key][2]
|
|
|
|
|
|
|
|
|
2018-09-15 06:17:04 +02:00
|
|
|
LINK_TYPE_HANDLERS = {
|
2021-02-12 08:20:45 +01:00
|
|
|
"gear": gear_handle_match,
|
|
|
|
"stream": stream_handle_match,
|
2023-06-26 20:38:34 +02:00
|
|
|
"message": message_handle_match,
|
2023-10-26 03:56:57 +02:00
|
|
|
"help": help_handle_match,
|
2018-09-15 06:17:04 +02:00
|
|
|
}
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2020-10-19 06:37:43 +02:00
|
|
|
class RelativeLinksHelpExtension(Extension):
|
2023-10-12 19:43:45 +02:00
|
|
|
@override
|
2020-10-19 06:37:43 +02:00
|
|
|
def extendMarkdown(self, md: Markdown) -> None:
|
2021-05-08 02:36:30 +02:00
|
|
|
"""Add RelativeLinksHelpExtension to the Markdown instance."""
|
2018-09-15 06:17:04 +02:00
|
|
|
md.registerExtension(self)
|
2021-09-17 19:01:36 +02:00
|
|
|
md.preprocessors.register(
|
|
|
|
RelativeLinks(), "help_relative_links", PREPROCESSOR_PRIORITES["help_relative_links"]
|
|
|
|
)
|
2018-09-15 06:17:04 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2022-04-27 04:23:43 +02:00
|
|
|
relative_help_links: bool = False
|
2018-09-15 06:17:04 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2018-09-15 06:17:04 +02:00
|
|
|
def set_relative_help_links(value: bool) -> None:
|
|
|
|
global relative_help_links
|
|
|
|
relative_help_links = value
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2018-09-15 06:17:04 +02:00
|
|
|
class RelativeLinks(Preprocessor):
|
2023-10-12 19:43:45 +02:00
|
|
|
@override
|
2018-09-15 06:17:04 +02:00
|
|
|
def run(self, lines: List[str]) -> List[str]:
|
|
|
|
done = False
|
|
|
|
while not done:
|
|
|
|
for line in lines:
|
|
|
|
loc = lines.index(line)
|
|
|
|
match = REGEXP.search(line)
|
|
|
|
|
|
|
|
if match:
|
|
|
|
text = [self.handleMatch(match)]
|
|
|
|
# The line that contains the directive to include the macro
|
|
|
|
# may be preceded or followed by text or tags, in that case
|
|
|
|
# we need to make sure that any preceding or following text
|
|
|
|
# stays the same.
|
|
|
|
line_split = REGEXP.split(line, maxsplit=0)
|
|
|
|
preceding = line_split[0]
|
|
|
|
following = line_split[-1]
|
2020-09-02 06:59:07 +02:00
|
|
|
text = [preceding, *text, following]
|
2021-02-12 08:19:30 +01:00
|
|
|
lines = lines[:loc] + text + lines[loc + 1 :]
|
2018-09-15 06:17:04 +02:00
|
|
|
break
|
|
|
|
else:
|
|
|
|
done = True
|
|
|
|
return lines
|
|
|
|
|
|
|
|
def handleMatch(self, match: Match[str]) -> str:
|
2021-02-12 08:20:45 +01:00
|
|
|
return LINK_TYPE_HANDLERS[match.group("link_type")](match.group("key"))
|
2018-09-15 06:17:04 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2018-09-15 06:17:04 +02:00
|
|
|
def makeExtension(*args: Any, **kwargs: Any) -> RelativeLinksHelpExtension:
|
|
|
|
return RelativeLinksHelpExtension(*args, **kwargs)
|