We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add "Privacy and security" section to personal Settings menu 
Some personal settings are hard to find right now, and some settings pages have too many different kinds of settings. We should make the settings easier to navigate by splitting "Your account" into two sections:

1. **Profile** (1st on the list). We can try removing all the section headers and see if it's OK or confusing.
Settings (in order): Full name, Profile picture, "Deactivate account" button, everything currently under **Your account > Profile** (custom fields).

I'm not entirely sure about the "Deactivate account" button placement; we can play with it.

2. **Privacy and security** (2nd on the list) 
Settings (in order):
  a. **User settings**: Email, password, role
  b.  **Presence** (currently under **Notifications**)
  c.  **API key**



--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `zerver/lib/markdown/help_relative_links.py`
Content:
```
1 import re
2 from typing import Any, List, Match, Optional
3 
4 from markdown import Markdown
5 from markdown.extensions import Extension
6 from markdown.preprocessors import Preprocessor
7 
8 # There is a lot of duplicated code between this file and
9 # help_settings_links.py. So if you're making a change here consider making
10 # it there as well.
11 
12 REGEXP = re.compile(r"\{relative\|(?P<link_type>.*?)\|(?P<key>.*?)\}")
13 
14 gear_info = {
15     # The pattern is key: [name, link]
16     # key is from REGEXP: `{relative|gear|key}`
17     # name is what the item is called in the gear menu: `Select **name**.`
18     # link is used for relative links: `Select [name](link).`
19     "manage-streams": ["Manage streams", "/#streams/subscribed"],
20     "settings": ["Settings", "/#settings/your-account"],
21     "manage-organization": ["Manage organization", "/#organization/organization-profile"],
22     "integrations": ["Integrations", "/integrations"],
23     "stats": ["Usage statistics", "/stats"],
24     "plans": ["Plans and pricing", "/plans"],
25     "billing": ["Billing", "/billing"],
26     "invite": ["Invite users", "/#invite"],
27 }
28 
29 gear_instructions = """
30 1. From your desktop, click on the **gear**
31    (<i class="fa fa-cog"></i>) in the upper right corner.
32 
33 1. Select {item}.
34 """
35 
36 
37 def gear_handle_match(key: str) -> str:
38     if relative_help_links:
39         item = f"[{gear_info[key][0]}]({gear_info[key][1]})"
40     else:
41         item = f"**{gear_info[key][0]}**"
42     return gear_instructions.format(item=item)
43 
44 
45 stream_info = {
46     "all": ["All streams", "/#streams/all"],
47     "subscribed": ["Your streams", "/#streams/subscribed"],
48 }
49 
50 stream_instructions_no_link = """
51 1. From your desktop, click on the **gear**
52    (<i class="fa fa-cog"></i>) in the upper right corner.
53 
54 1. Click **Manage streams**.
55 """
56 
57 
58 def stream_handle_match(key: str) -> str:
59     if relative_help_links:
60         return f"1. Go to [{stream_info[key][0]}]({stream_info[key][1]})."
61     if key == "all":
62         return stream_instructions_no_link + "\n\n1. Click **All streams** in the upper left."
63     return stream_instructions_no_link
64 
65 
66 LINK_TYPE_HANDLERS = {
67     "gear": gear_handle_match,
68     "stream": stream_handle_match,
69 }
70 
71 
72 class RelativeLinksHelpExtension(Extension):
73     def extendMarkdown(self, md: Markdown) -> None:
74         """Add RelativeLinksHelpExtension to the Markdown instance."""
75         md.registerExtension(self)
76         md.preprocessors.register(RelativeLinks(), "help_relative_links", 520)
77 
78 
79 relative_help_links: Optional[bool] = None
80 
81 
82 def set_relative_help_links(value: bool) -> None:
83     global relative_help_links
84     relative_help_links = value
85 
86 
87 class RelativeLinks(Preprocessor):
88     def run(self, lines: List[str]) -> List[str]:
89         done = False
90         while not done:
91             for line in lines:
92                 loc = lines.index(line)
93                 match = REGEXP.search(line)
94 
95                 if match:
96                     text = [self.handleMatch(match)]
97                     # The line that contains the directive to include the macro
98                     # may be preceded or followed by text or tags, in that case
99                     # we need to make sure that any preceding or following text
100                     # stays the same.
101                     line_split = REGEXP.split(line, maxsplit=0)
102                     preceding = line_split[0]
103                     following = line_split[-1]
104                     text = [preceding, *text, following]
105                     lines = lines[:loc] + text + lines[loc + 1 :]
106                     break
107             else:
108                 done = True
109         return lines
110 
111     def handleMatch(self, match: Match[str]) -> str:
112         return LINK_TYPE_HANDLERS[match.group("link_type")](match.group("key"))
113 
114 
115 def makeExtension(*args: Any, **kwargs: Any) -> RelativeLinksHelpExtension:
116     return RelativeLinksHelpExtension(*args, **kwargs)
117
```

Path: `zerver/lib/markdown/help_settings_links.py`
Content:
```
1 import re
2 from typing import Any, List, Match, Optional
3 
4 from markdown import Markdown
5 from markdown.extensions import Extension
6 from markdown.preprocessors import Preprocessor
7 
8 # There is a lot of duplicated code between this file and
9 # help_relative_links.py. So if you're making a change here consider making
10 # it there as well.
11 
12 REGEXP = re.compile(r"\{settings_tab\|(?P<setting_identifier>.*?)\}")
13 
14 link_mapping = {
15     # a mapping from the setting identifier that is the same as the final URL
16     # breadcrumb to that setting to the name of its setting type, the setting
17     # name as it appears in the user interface, and a relative link that can
18     # be used to get to that setting
19     "your-account": ["Settings", "Your account", "/#settings/your-account"],
20     "display-settings": ["Settings", "Display settings", "/#settings/display-settings"],
21     "notifications": ["Settings", "Notifications", "/#settings/notifications"],
22     "your-bots": ["Settings", "Your bots", "/#settings/your-bots"],
23     "alert-words": ["Settings", "Alert words", "/#settings/alert-words"],
24     "uploaded-files": ["Settings", "Uploaded files", "/#settings/uploaded-files"],
25     "muted-topics": ["Settings", "Muted topics", "/#settings/muted-topics"],
26     "muted-users": ["Settings", "Muted users", "/#settings/muted-users"],
27     "organization-profile": [
28         "Manage organization",
29         "Organization profile",
30         "/#organization/organization-profile",
31     ],
32     "organization-settings": [
33         "Manage organization",
34         "Organization settings",
35         "/#organization/organization-settings",
36     ],
37     "organization-permissions": [
38         "Manage organization",
39         "Organization permissions",
40         "/#organization/organization-permissions",
41     ],
42     "emoji-settings": ["Manage organization", "Custom emoji", "/#organization/emoji-settings"],
43     "auth-methods": [
44         "Manage organization",
45         "Authentication methods",
46         "/#organization/auth-methods",
47     ],
48     "user-groups-admin": ["Manage organization", "User groups", "/#organization/user-groups-admin"],
49     "user-list-admin": ["Manage organization", "Users", "/#organization/user-list-admin"],
50     "deactivated-users-admin": [
51         "Manage organization",
52         "Deactivated users",
53         "/#organization/deactivated-users-admin",
54     ],
55     "bot-list-admin": ["Manage organization", "Bots", "/#organization/bot-list-admin"],
56     "default-streams-list": [
57         "Manage organization",
58         "Default streams",
59         "/#organization/default-streams-list",
60     ],
61     "linkifier-settings": [
62         "Manage organization",
63         "Linkifiers",
64         "/#organization/linkifier-settings",
65     ],
66     "playground-settings": [
67         "Manage organization",
68         "Code playgrounds",
69         "/#organization/playground-settings",
70     ],
71     "profile-field-settings": [
72         "Manage organization",
73         "Custom profile fields",
74         "/#organization/profile-field-settings",
75     ],
76     "invites-list-admin": [
77         "Manage organization",
78         "Invitations",
79         "/#organization/invites-list-admin",
80     ],
81     "data-exports-admin": [
82         "Manage organization",
83         "Data exports",
84         "/#organization/data-exports-admin",
85     ],
86 }
87 
88 settings_markdown = """
89 1. From your desktop, click on the **gear**
90    (<i class="fa fa-cog"></i>) in the upper right corner.
91 
92 1. Select **{setting_type_name}**.
93 
94 1. On the left, click {setting_reference}.
95 """
96 
97 
98 class SettingHelpExtension(Extension):
99     def extendMarkdown(self, md: Markdown) -> None:
100         """Add SettingHelpExtension to the Markdown instance."""
101         md.registerExtension(self)
102         md.preprocessors.register(Setting(), "setting", 515)
103 
104 
105 relative_settings_links: Optional[bool] = None
106 
107 
108 def set_relative_settings_links(value: bool) -> None:
109     global relative_settings_links
110     relative_settings_links = value
111 
112 
113 class Setting(Preprocessor):
114     def run(self, lines: List[str]) -> List[str]:
115         done = False
116         while not done:
117             for line in lines:
118                 loc = lines.index(line)
119                 match = REGEXP.search(line)
120 
121                 if match:
122                     text = [self.handleMatch(match)]
123                     # The line that contains the directive to include the macro
124                     # may be preceded or followed by text or tags, in that case
125                     # we need to make sure that any preceding or following text
126                     # stays the same.
127                     line_split = REGEXP.split(line, maxsplit=0)
128                     preceding = line_split[0]
129                     following = line_split[-1]
130                     text = [preceding, *text, following]
131                     lines = lines[:loc] + text + lines[loc + 1 :]
132                     break
133             else:
134                 done = True
135         return lines
136 
137     def handleMatch(self, match: Match[str]) -> str:
138         setting_identifier = match.group("setting_identifier")
139         setting_type_name = link_mapping[setting_identifier][0]
140         setting_name = link_mapping[setting_identifier][1]
141         setting_link = link_mapping[setting_identifier][2]
142         if relative_settings_links:
143             return f"1. Go to [{setting_name}]({setting_link})."
144         return settings_markdown.format(
145             setting_type_name=setting_type_name,
146             setting_reference=f"**{setting_name}**",
147         )
148 
149 
150 def makeExtension(*args: Any, **kwargs: Any) -> SettingHelpExtension:
151     return SettingHelpExtension(*args, **kwargs)
152
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/zerver/lib/markdown/help_relative_links.py b/zerver/lib/markdown/help_relative_links.py
--- a/zerver/lib/markdown/help_relative_links.py
+++ b/zerver/lib/markdown/help_relative_links.py
@@ -17,7 +17,7 @@
     # name is what the item is called in the gear menu: `Select **name**.`
     # link is used for relative links: `Select [name](link).`
     "manage-streams": ["Manage streams", "/#streams/subscribed"],
-    "settings": ["Settings", "/#settings/your-account"],
+    "settings": ["Settings", "/#settings/profile"],
     "manage-organization": ["Manage organization", "/#organization/organization-profile"],
     "integrations": ["Integrations", "/integrations"],
     "stats": ["Usage statistics", "/stats"],
diff --git a/zerver/lib/markdown/help_settings_links.py b/zerver/lib/markdown/help_settings_links.py
--- a/zerver/lib/markdown/help_settings_links.py
+++ b/zerver/lib/markdown/help_settings_links.py
@@ -16,7 +16,8 @@
     # breadcrumb to that setting to the name of its setting type, the setting
     # name as it appears in the user interface, and a relative link that can
     # be used to get to that setting
-    "your-account": ["Settings", "Your account", "/#settings/your-account"],
+    "profile": ["Settings", "Profile", "/#settings/profile"],
+    "account-and-privacy": ["Settings", "Account & privacy", "/#settings/account-and-privacy"],
     "display-settings": ["Settings", "Display settings", "/#settings/display-settings"],
     "notifications": ["Settings", "Notifications", "/#settings/notifications"],
     "your-bots": ["Settings", "Your bots", "/#settings/your-bots"],

{"golden_diff": "diff --git a/zerver/lib/markdown/help_relative_links.py b/zerver/lib/markdown/help_relative_links.py\n--- a/zerver/lib/markdown/help_relative_links.py\n+++ b/zerver/lib/markdown/help_relative_links.py\n@@ -17,7 +17,7 @@\n     # name is what the item is called in the gear menu: `Select **name**.`\n     # link is used for relative links: `Select [name](link).`\n     \"manage-streams\": [\"Manage streams\", \"/#streams/subscribed\"],\n-    \"settings\": [\"Settings\", \"/#settings/your-account\"],\n+    \"settings\": [\"Settings\", \"/#settings/profile\"],\n     \"manage-organization\": [\"Manage organization\", \"/#organization/organization-profile\"],\n     \"integrations\": [\"Integrations\", \"/integrations\"],\n     \"stats\": [\"Usage statistics\", \"/stats\"],\ndiff --git a/zerver/lib/markdown/help_settings_links.py b/zerver/lib/markdown/help_settings_links.py\n--- a/zerver/lib/markdown/help_settings_links.py\n+++ b/zerver/lib/markdown/help_settings_links.py\n@@ -16,7 +16,8 @@\n     # breadcrumb to that setting to the name of its setting type, the setting\n     # name as it appears in the user interface, and a relative link that can\n     # be used to get to that setting\n-    \"your-account\": [\"Settings\", \"Your account\", \"/#settings/your-account\"],\n+    \"profile\": [\"Settings\", \"Profile\", \"/#settings/profile\"],\n+    \"account-and-privacy\": [\"Settings\", \"Account & privacy\", \"/#settings/account-and-privacy\"],\n     \"display-settings\": [\"Settings\", \"Display settings\", \"/#settings/display-settings\"],\n     \"notifications\": [\"Settings\", \"Notifications\", \"/#settings/notifications\"],\n     \"your-bots\": [\"Settings\", \"Your bots\", \"/#settings/your-bots\"],\n", "issue": "Add \"Privacy and security\" section to personal Settings menu \nSome personal settings are hard to find right now, and some settings pages have too many different kinds of settings. We should make the settings easier to navigate by splitting \"Your account\" into two sections:\r\n\r\n1. **Profile** (1st on the list). We can try removing all the section headers and see if it's OK or confusing.\r\nSettings (in order): Full name, Profile picture, \"Deactivate account\" button, everything currently under **Your account > Profile** (custom fields).\r\n\r\nI'm not entirely sure about the \"Deactivate account\" button placement; we can play with it.\r\n\r\n2. **Privacy and security** (2nd on the list) \r\nSettings (in order):\r\n  a. **User settings**: Email, password, role\r\n  b.  **Presence** (currently under **Notifications**)\r\n  c.  **API key**\r\n\r\n\n", "before_files": [{"content": "import re\nfrom typing import Any, List, Match, Optional\n\nfrom markdown import Markdown\nfrom markdown.extensions import Extension\nfrom markdown.preprocessors import Preprocessor\n\n# There is a lot of duplicated code between this file and\n# help_settings_links.py. So if you're making a change here consider making\n# it there as well.\n\nREGEXP = re.compile(r\"\\{relative\\|(?P<link_type>.*?)\\|(?P<key>.*?)\\}\")\n\ngear_info = {\n    # The pattern is key: [name, link]\n    # key is from REGEXP: `{relative|gear|key}`\n    # name is what the item is called in the gear menu: `Select **name**.`\n    # link is used for relative links: `Select [name](link).`\n    \"manage-streams\": [\"Manage streams\", \"/#streams/subscribed\"],\n    \"settings\": [\"Settings\", \"/#settings/your-account\"],\n    \"manage-organization\": [\"Manage organization\", \"/#organization/organization-profile\"],\n    \"integrations\": [\"Integrations\", \"/integrations\"],\n    \"stats\": [\"Usage statistics\", \"/stats\"],\n    \"plans\": [\"Plans and pricing\", \"/plans\"],\n    \"billing\": [\"Billing\", \"/billing\"],\n    \"invite\": [\"Invite users\", \"/#invite\"],\n}\n\ngear_instructions = \"\"\"\n1. From your desktop, click on the **gear**\n   (<i class=\"fa fa-cog\"></i>) in the upper right corner.\n\n1. Select {item}.\n\"\"\"\n\n\ndef gear_handle_match(key: str) -> str:\n    if relative_help_links:\n        item = f\"[{gear_info[key][0]}]({gear_info[key][1]})\"\n    else:\n        item = f\"**{gear_info[key][0]}**\"\n    return gear_instructions.format(item=item)\n\n\nstream_info = {\n    \"all\": [\"All streams\", \"/#streams/all\"],\n    \"subscribed\": [\"Your streams\", \"/#streams/subscribed\"],\n}\n\nstream_instructions_no_link = \"\"\"\n1. From your desktop, click on the **gear**\n   (<i class=\"fa fa-cog\"></i>) in the upper right corner.\n\n1. Click **Manage streams**.\n\"\"\"\n\n\ndef stream_handle_match(key: str) -> str:\n    if relative_help_links:\n        return f\"1. Go to [{stream_info[key][0]}]({stream_info[key][1]}).\"\n    if key == \"all\":\n        return stream_instructions_no_link + \"\\n\\n1. Click **All streams** in the upper left.\"\n    return stream_instructions_no_link\n\n\nLINK_TYPE_HANDLERS = {\n    \"gear\": gear_handle_match,\n    \"stream\": stream_handle_match,\n}\n\n\nclass RelativeLinksHelpExtension(Extension):\n    def extendMarkdown(self, md: Markdown) -> None:\n        \"\"\"Add RelativeLinksHelpExtension to the Markdown instance.\"\"\"\n        md.registerExtension(self)\n        md.preprocessors.register(RelativeLinks(), \"help_relative_links\", 520)\n\n\nrelative_help_links: Optional[bool] = None\n\n\ndef set_relative_help_links(value: bool) -> None:\n    global relative_help_links\n    relative_help_links = value\n\n\nclass RelativeLinks(Preprocessor):\n    def run(self, lines: List[str]) -> List[str]:\n        done = False\n        while not done:\n            for line in lines:\n                loc = lines.index(line)\n                match = REGEXP.search(line)\n\n                if match:\n                    text = [self.handleMatch(match)]\n                    # The line that contains the directive to include the macro\n                    # may be preceded or followed by text or tags, in that case\n                    # we need to make sure that any preceding or following text\n                    # stays the same.\n                    line_split = REGEXP.split(line, maxsplit=0)\n                    preceding = line_split[0]\n                    following = line_split[-1]\n                    text = [preceding, *text, following]\n                    lines = lines[:loc] + text + lines[loc + 1 :]\n                    break\n            else:\n                done = True\n        return lines\n\n    def handleMatch(self, match: Match[str]) -> str:\n        return LINK_TYPE_HANDLERS[match.group(\"link_type\")](match.group(\"key\"))\n\n\ndef makeExtension(*args: Any, **kwargs: Any) -> RelativeLinksHelpExtension:\n    return RelativeLinksHelpExtension(*args, **kwargs)\n", "path": "zerver/lib/markdown/help_relative_links.py"}, {"content": "import re\nfrom typing import Any, List, Match, Optional\n\nfrom markdown import Markdown\nfrom markdown.extensions import Extension\nfrom markdown.preprocessors import Preprocessor\n\n# There is a lot of duplicated code between this file and\n# help_relative_links.py. So if you're making a change here consider making\n# it there as well.\n\nREGEXP = re.compile(r\"\\{settings_tab\\|(?P<setting_identifier>.*?)\\}\")\n\nlink_mapping = {\n    # a mapping from the setting identifier that is the same as the final URL\n    # breadcrumb to that setting to the name of its setting type, the setting\n    # name as it appears in the user interface, and a relative link that can\n    # be used to get to that setting\n    \"your-account\": [\"Settings\", \"Your account\", \"/#settings/your-account\"],\n    \"display-settings\": [\"Settings\", \"Display settings\", \"/#settings/display-settings\"],\n    \"notifications\": [\"Settings\", \"Notifications\", \"/#settings/notifications\"],\n    \"your-bots\": [\"Settings\", \"Your bots\", \"/#settings/your-bots\"],\n    \"alert-words\": [\"Settings\", \"Alert words\", \"/#settings/alert-words\"],\n    \"uploaded-files\": [\"Settings\", \"Uploaded files\", \"/#settings/uploaded-files\"],\n    \"muted-topics\": [\"Settings\", \"Muted topics\", \"/#settings/muted-topics\"],\n    \"muted-users\": [\"Settings\", \"Muted users\", \"/#settings/muted-users\"],\n    \"organization-profile\": [\n        \"Manage organization\",\n        \"Organization profile\",\n        \"/#organization/organization-profile\",\n    ],\n    \"organization-settings\": [\n        \"Manage organization\",\n        \"Organization settings\",\n        \"/#organization/organization-settings\",\n    ],\n    \"organization-permissions\": [\n        \"Manage organization\",\n        \"Organization permissions\",\n        \"/#organization/organization-permissions\",\n    ],\n    \"emoji-settings\": [\"Manage organization\", \"Custom emoji\", \"/#organization/emoji-settings\"],\n    \"auth-methods\": [\n        \"Manage organization\",\n        \"Authentication methods\",\n        \"/#organization/auth-methods\",\n    ],\n    \"user-groups-admin\": [\"Manage organization\", \"User groups\", \"/#organization/user-groups-admin\"],\n    \"user-list-admin\": [\"Manage organization\", \"Users\", \"/#organization/user-list-admin\"],\n    \"deactivated-users-admin\": [\n        \"Manage organization\",\n        \"Deactivated users\",\n        \"/#organization/deactivated-users-admin\",\n    ],\n    \"bot-list-admin\": [\"Manage organization\", \"Bots\", \"/#organization/bot-list-admin\"],\n    \"default-streams-list\": [\n        \"Manage organization\",\n        \"Default streams\",\n        \"/#organization/default-streams-list\",\n    ],\n    \"linkifier-settings\": [\n        \"Manage organization\",\n        \"Linkifiers\",\n        \"/#organization/linkifier-settings\",\n    ],\n    \"playground-settings\": [\n        \"Manage organization\",\n        \"Code playgrounds\",\n        \"/#organization/playground-settings\",\n    ],\n    \"profile-field-settings\": [\n        \"Manage organization\",\n        \"Custom profile fields\",\n        \"/#organization/profile-field-settings\",\n    ],\n    \"invites-list-admin\": [\n        \"Manage organization\",\n        \"Invitations\",\n        \"/#organization/invites-list-admin\",\n    ],\n    \"data-exports-admin\": [\n        \"Manage organization\",\n        \"Data exports\",\n        \"/#organization/data-exports-admin\",\n    ],\n}\n\nsettings_markdown = \"\"\"\n1. From your desktop, click on the **gear**\n   (<i class=\"fa fa-cog\"></i>) in the upper right corner.\n\n1. Select **{setting_type_name}**.\n\n1. On the left, click {setting_reference}.\n\"\"\"\n\n\nclass SettingHelpExtension(Extension):\n    def extendMarkdown(self, md: Markdown) -> None:\n        \"\"\"Add SettingHelpExtension to the Markdown instance.\"\"\"\n        md.registerExtension(self)\n        md.preprocessors.register(Setting(), \"setting\", 515)\n\n\nrelative_settings_links: Optional[bool] = None\n\n\ndef set_relative_settings_links(value: bool) -> None:\n    global relative_settings_links\n    relative_settings_links = value\n\n\nclass Setting(Preprocessor):\n    def run(self, lines: List[str]) -> List[str]:\n        done = False\n        while not done:\n            for line in lines:\n                loc = lines.index(line)\n                match = REGEXP.search(line)\n\n                if match:\n                    text = [self.handleMatch(match)]\n                    # The line that contains the directive to include the macro\n                    # may be preceded or followed by text or tags, in that case\n                    # we need to make sure that any preceding or following text\n                    # stays the same.\n                    line_split = REGEXP.split(line, maxsplit=0)\n                    preceding = line_split[0]\n                    following = line_split[-1]\n                    text = [preceding, *text, following]\n                    lines = lines[:loc] + text + lines[loc + 1 :]\n                    break\n            else:\n                done = True\n        return lines\n\n    def handleMatch(self, match: Match[str]) -> str:\n        setting_identifier = match.group(\"setting_identifier\")\n        setting_type_name = link_mapping[setting_identifier][0]\n        setting_name = link_mapping[setting_identifier][1]\n        setting_link = link_mapping[setting_identifier][2]\n        if relative_settings_links:\n            return f\"1. Go to [{setting_name}]({setting_link}).\"\n        return settings_markdown.format(\n            setting_type_name=setting_type_name,\n            setting_reference=f\"**{setting_name}**\",\n        )\n\n\ndef makeExtension(*args: Any, **kwargs: Any) -> SettingHelpExtension:\n    return SettingHelpExtension(*args, **kwargs)\n", "path": "zerver/lib/markdown/help_settings_links.py"}], "after_files": [{"content": "import re\nfrom typing import Any, List, Match, Optional\n\nfrom markdown import Markdown\nfrom markdown.extensions import Extension\nfrom markdown.preprocessors import Preprocessor\n\n# There is a lot of duplicated code between this file and\n# help_settings_links.py. So if you're making a change here consider making\n# it there as well.\n\nREGEXP = re.compile(r\"\\{relative\\|(?P<link_type>.*?)\\|(?P<key>.*?)\\}\")\n\ngear_info = {\n    # The pattern is key: [name, link]\n    # key is from REGEXP: `{relative|gear|key}`\n    # name is what the item is called in the gear menu: `Select **name**.`\n    # link is used for relative links: `Select [name](link).`\n    \"manage-streams\": [\"Manage streams\", \"/#streams/subscribed\"],\n    \"settings\": [\"Settings\", \"/#settings/profile\"],\n    \"manage-organization\": [\"Manage organization\", \"/#organization/organization-profile\"],\n    \"integrations\": [\"Integrations\", \"/integrations\"],\n    \"stats\": [\"Usage statistics\", \"/stats\"],\n    \"plans\": [\"Plans and pricing\", \"/plans\"],\n    \"billing\": [\"Billing\", \"/billing\"],\n    \"invite\": [\"Invite users\", \"/#invite\"],\n}\n\ngear_instructions = \"\"\"\n1. From your desktop, click on the **gear**\n   (<i class=\"fa fa-cog\"></i>) in the upper right corner.\n\n1. Select {item}.\n\"\"\"\n\n\ndef gear_handle_match(key: str) -> str:\n    if relative_help_links:\n        item = f\"[{gear_info[key][0]}]({gear_info[key][1]})\"\n    else:\n        item = f\"**{gear_info[key][0]}**\"\n    return gear_instructions.format(item=item)\n\n\nstream_info = {\n    \"all\": [\"All streams\", \"/#streams/all\"],\n    \"subscribed\": [\"Your streams\", \"/#streams/subscribed\"],\n}\n\nstream_instructions_no_link = \"\"\"\n1. From your desktop, click on the **gear**\n   (<i class=\"fa fa-cog\"></i>) in the upper right corner.\n\n1. Click **Manage streams**.\n\"\"\"\n\n\ndef stream_handle_match(key: str) -> str:\n    if relative_help_links:\n        return f\"1. Go to [{stream_info[key][0]}]({stream_info[key][1]}).\"\n    if key == \"all\":\n        return stream_instructions_no_link + \"\\n\\n1. Click **All streams** in the upper left.\"\n    return stream_instructions_no_link\n\n\nLINK_TYPE_HANDLERS = {\n    \"gear\": gear_handle_match,\n    \"stream\": stream_handle_match,\n}\n\n\nclass RelativeLinksHelpExtension(Extension):\n    def extendMarkdown(self, md: Markdown) -> None:\n        \"\"\"Add RelativeLinksHelpExtension to the Markdown instance.\"\"\"\n        md.registerExtension(self)\n        md.preprocessors.register(RelativeLinks(), \"help_relative_links\", 520)\n\n\nrelative_help_links: Optional[bool] = None\n\n\ndef set_relative_help_links(value: bool) -> None:\n    global relative_help_links\n    relative_help_links = value\n\n\nclass RelativeLinks(Preprocessor):\n    def run(self, lines: List[str]) -> List[str]:\n        done = False\n        while not done:\n            for line in lines:\n                loc = lines.index(line)\n                match = REGEXP.search(line)\n\n                if match:\n                    text = [self.handleMatch(match)]\n                    # The line that contains the directive to include the macro\n                    # may be preceded or followed by text or tags, in that case\n                    # we need to make sure that any preceding or following text\n                    # stays the same.\n                    line_split = REGEXP.split(line, maxsplit=0)\n                    preceding = line_split[0]\n                    following = line_split[-1]\n                    text = [preceding, *text, following]\n                    lines = lines[:loc] + text + lines[loc + 1 :]\n                    break\n            else:\n                done = True\n        return lines\n\n    def handleMatch(self, match: Match[str]) -> str:\n        return LINK_TYPE_HANDLERS[match.group(\"link_type\")](match.group(\"key\"))\n\n\ndef makeExtension(*args: Any, **kwargs: Any) -> RelativeLinksHelpExtension:\n    return RelativeLinksHelpExtension(*args, **kwargs)\n", "path": "zerver/lib/markdown/help_relative_links.py"}, {"content": "import re\nfrom typing import Any, List, Match, Optional\n\nfrom markdown import Markdown\nfrom markdown.extensions import Extension\nfrom markdown.preprocessors import Preprocessor\n\n# There is a lot of duplicated code between this file and\n# help_relative_links.py. So if you're making a change here consider making\n# it there as well.\n\nREGEXP = re.compile(r\"\\{settings_tab\\|(?P<setting_identifier>.*?)\\}\")\n\nlink_mapping = {\n    # a mapping from the setting identifier that is the same as the final URL\n    # breadcrumb to that setting to the name of its setting type, the setting\n    # name as it appears in the user interface, and a relative link that can\n    # be used to get to that setting\n    \"profile\": [\"Settings\", \"Profile\", \"/#settings/profile\"],\n    \"account-and-privacy\": [\"Settings\", \"Account & privacy\", \"/#settings/account-and-privacy\"],\n    \"display-settings\": [\"Settings\", \"Display settings\", \"/#settings/display-settings\"],\n    \"notifications\": [\"Settings\", \"Notifications\", \"/#settings/notifications\"],\n    \"your-bots\": [\"Settings\", \"Your bots\", \"/#settings/your-bots\"],\n    \"alert-words\": [\"Settings\", \"Alert words\", \"/#settings/alert-words\"],\n    \"uploaded-files\": [\"Settings\", \"Uploaded files\", \"/#settings/uploaded-files\"],\n    \"muted-topics\": [\"Settings\", \"Muted topics\", \"/#settings/muted-topics\"],\n    \"muted-users\": [\"Settings\", \"Muted users\", \"/#settings/muted-users\"],\n    \"organization-profile\": [\n        \"Manage organization\",\n        \"Organization profile\",\n        \"/#organization/organization-profile\",\n    ],\n    \"organization-settings\": [\n        \"Manage organization\",\n        \"Organization settings\",\n        \"/#organization/organization-settings\",\n    ],\n    \"organization-permissions\": [\n        \"Manage organization\",\n        \"Organization permissions\",\n        \"/#organization/organization-permissions\",\n    ],\n    \"emoji-settings\": [\"Manage organization\", \"Custom emoji\", \"/#organization/emoji-settings\"],\n    \"auth-methods\": [\n        \"Manage organization\",\n        \"Authentication methods\",\n        \"/#organization/auth-methods\",\n    ],\n    \"user-groups-admin\": [\"Manage organization\", \"User groups\", \"/#organization/user-groups-admin\"],\n    \"user-list-admin\": [\"Manage organization\", \"Users\", \"/#organization/user-list-admin\"],\n    \"deactivated-users-admin\": [\n        \"Manage organization\",\n        \"Deactivated users\",\n        \"/#organization/deactivated-users-admin\",\n    ],\n    \"bot-list-admin\": [\"Manage organization\", \"Bots\", \"/#organization/bot-list-admin\"],\n    \"default-streams-list\": [\n        \"Manage organization\",\n        \"Default streams\",\n        \"/#organization/default-streams-list\",\n    ],\n    \"linkifier-settings\": [\n        \"Manage organization\",\n        \"Linkifiers\",\n        \"/#organization/linkifier-settings\",\n    ],\n    \"playground-settings\": [\n        \"Manage organization\",\n        \"Code playgrounds\",\n        \"/#organization/playground-settings\",\n    ],\n    \"profile-field-settings\": [\n        \"Manage organization\",\n        \"Custom profile fields\",\n        \"/#organization/profile-field-settings\",\n    ],\n    \"invites-list-admin\": [\n        \"Manage organization\",\n        \"Invitations\",\n        \"/#organization/invites-list-admin\",\n    ],\n    \"data-exports-admin\": [\n        \"Manage organization\",\n        \"Data exports\",\n        \"/#organization/data-exports-admin\",\n    ],\n}\n\nsettings_markdown = \"\"\"\n1. From your desktop, click on the **gear**\n   (<i class=\"fa fa-cog\"></i>) in the upper right corner.\n\n1. Select **{setting_type_name}**.\n\n1. On the left, click {setting_reference}.\n\"\"\"\n\n\nclass SettingHelpExtension(Extension):\n    def extendMarkdown(self, md: Markdown) -> None:\n        \"\"\"Add SettingHelpExtension to the Markdown instance.\"\"\"\n        md.registerExtension(self)\n        md.preprocessors.register(Setting(), \"setting\", 515)\n\n\nrelative_settings_links: Optional[bool] = None\n\n\ndef set_relative_settings_links(value: bool) -> None:\n    global relative_settings_links\n    relative_settings_links = value\n\n\nclass Setting(Preprocessor):\n    def run(self, lines: List[str]) -> List[str]:\n        done = False\n        while not done:\n            for line in lines:\n                loc = lines.index(line)\n                match = REGEXP.search(line)\n\n                if match:\n                    text = [self.handleMatch(match)]\n                    # The line that contains the directive to include the macro\n                    # may be preceded or followed by text or tags, in that case\n                    # we need to make sure that any preceding or following text\n                    # stays the same.\n                    line_split = REGEXP.split(line, maxsplit=0)\n                    preceding = line_split[0]\n                    following = line_split[-1]\n                    text = [preceding, *text, following]\n                    lines = lines[:loc] + text + lines[loc + 1 :]\n                    break\n            else:\n                done = True\n        return lines\n\n    def handleMatch(self, match: Match[str]) -> str:\n        setting_identifier = match.group(\"setting_identifier\")\n        setting_type_name = link_mapping[setting_identifier][0]\n        setting_name = link_mapping[setting_identifier][1]\n        setting_link = link_mapping[setting_identifier][2]\n        if relative_settings_links:\n            return f\"1. Go to [{setting_name}]({setting_link}).\"\n        return settings_markdown.format(\n            setting_type_name=setting_type_name,\n            setting_reference=f\"**{setting_name}**\",\n        )\n\n\ndef makeExtension(*args: Any, **kwargs: Any) -> SettingHelpExtension:\n    return SettingHelpExtension(*args, **kwargs)\n", "path": "zerver/lib/markdown/help_settings_links.py"}]}