bugdown: Add {settings|my-setting} macro.

Tweaked by tabbott to add a test and fix a super subtle issue with the
relative_settings_link variable having been set once the first time a
/help article was rendered.
This commit is contained in:
Lyla Fischer
2018-04-17 22:31:57 -04:00
committed by Tim Abbott
parent 6e5d6da7f9
commit b24659b005
8 changed files with 109 additions and 14 deletions

View File

@@ -3,8 +3,7 @@
If enabled by your Zulip organization administrator, you can add custom
emojis to your organization for other members to use.
1. Go to the [Emoji Settings](/#organization/emoji-settings)
{!admin.md!}
{settings_tab|emoji-settings}
5. In the green section labeled **Add a new emoji**, find the **Emoji name** and
**Emoji URL** fields.

View File

@@ -6,8 +6,7 @@ simply use your existing gravatar.
You can also upload a custom avatar to Zulip.
1. Go to the [Your account](/#settings/your-account)
{!settings.md!}
{settings_tab|your-account}
2. Click the **Upload new avatar** button and choose an image to upload
as your avatar.

View File

@@ -3,8 +3,7 @@
If enabled by Zulip organization administrator, you can change your email address
using the following steps.
1. Go to the [Your account](/#settings/your-account)
{!settings.md!}
{settings_tab|your-account}
2. Click on the **[Change]** link beside your email address.

View File

@@ -2,8 +2,9 @@
## If you know your current password
1. Go to the [Your account](/#settings/your-account)
{!settings.md!}
{settings_tab|your-account}
2. Click the **Change password** button located underneath your name.
3. You will first be asked to enter your old password, and then to
enter a new password and to confirm it.

View File

@@ -3,15 +3,14 @@
We'd be sorry to see you go, but you can follow the following steps to
deactivate your Zulip account.
1. Go to the [Your account](/#settings/your-account)
{!settings.md!}
{settings_tab|your-account}
2. Click the **Deactivate account** button on the bottom of the
**Your account** section.
4. After clicking the **Deactivate account** button, a modal window titled
**Deactivate your account** will appear. To confirm the deletion of your
account, click the **Deactivate now** button.
account, click the **Deactivate now** button.
!!! warn ""
**Note:** Any bots that you maintain will be disabled when you

View File

@@ -0,0 +1,79 @@
import re
import markdown
from typing import Any, Dict, List, Optional, Union, Text
from typing.re import Match
from markdown.preprocessors import Preprocessor
REGEXP = re.compile(r'\{settings_tab\|(?P<setting_identifier>.*?)\}')
link_mapping = {
# a mapping from the setting identifier that is the same as the final URL
# 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'],
'emoji-settings': ['Manage organization', 'Custom emoji', '/#organization/emoji-settings'],
}
settings_markdown = """
1. From your desktop, click on the **gear**
(<i class="icon-vector-cog"></i>) in the upper right corner.
1. Select **%(setting_type_name)s**.
1. On the left, click %(setting_reference)s.
"""
class SettingHelpExtension(markdown.Extension):
def extendMarkdown(self, md: markdown.Markdown, md_globals: Dict[str, Any]) -> None:
""" Add SettingHelpExtension to the Markdown instance. """
md.registerExtension(self)
md.preprocessors.add('setting', Setting(), '_begin')
relative_settings_links = None
def set_relative_settings_links(value):
global relative_settings_links
relative_settings_links = value
class Setting(Preprocessor):
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]
text = [preceding] + text + [following]
lines = lines[:loc] + text + lines[loc+1:]
break
else:
done = True
return lines
def handleMatch(self, match: Match[Text]) -> Text:
setting_identifier = match.group('setting_identifier')
setting_type_name = link_mapping[setting_identifier][0]
setting_name = link_mapping[setting_identifier][1]
setting_link = link_mapping[setting_identifier][2]
if relative_settings_links:
setting_reference = "[%s](%s)" % (setting_name, setting_link)
else:
setting_reference = "**%s**" % (setting_name,)
instructions = settings_markdown % {'setting_type_name': setting_type_name,
'setting_reference': setting_reference}
return instructions
def makeExtension(*args: Any, **kwargs: Any) -> SettingHelpExtension:
return SettingHelpExtension(*args, **kwargs)

View File

@@ -14,6 +14,7 @@ from django.utils.safestring import mark_safe
import zerver.lib.bugdown.fenced_code
import zerver.lib.bugdown.api_arguments_table_generator
import zerver.lib.bugdown.api_code_examples
import zerver.lib.bugdown.help_settings_links
from zerver.lib.cache import ignore_unhashable_lru_cache
register = Library()
@@ -74,6 +75,14 @@ def render_markdown_path(markdown_file_path: str, context: Optional[Dict[Any, An
Note that this assumes that any HTML in the markdown file is
trusted; it is intended to be used for documentation, not user
data."""
if context is None:
context = {}
# We set this global hackishly
from zerver.lib.bugdown.help_settings_links import set_relative_settings_links
set_relative_settings_links(bool(context.get('html_settings_links')))
global md_extensions
global md_macro_extension
if md_extensions is None:
@@ -89,6 +98,7 @@ def render_markdown_path(markdown_file_path: str, context: Optional[Dict[Any, An
zerver.lib.bugdown.api_arguments_table_generator.makeExtension(
base_path='templates/zerver/api/'),
zerver.lib.bugdown.api_code_examples.makeExtension(),
zerver.lib.bugdown.help_settings_links.makeExtension(),
]
if md_macro_extension is None:
md_macro_extension = markdown_include.include.makeExtension(
@@ -100,9 +110,6 @@ def render_markdown_path(markdown_file_path: str, context: Optional[Dict[Any, An
md_engine = markdown.Markdown(extensions=md_extensions + [md_macro_extension])
md_engine.reset()
if context is None:
context = {}
jinja = engines['Jinja2']
markdown_string = jinja.env.loader.get_source(jinja.env, markdown_file_path)[0]
html = md_engine.convert(markdown_string)

View File

@@ -130,6 +130,18 @@ class HelpTest(ZulipTestCase):
self.assertEqual(result.status_code, 200)
self.assertIn('<a target="_blank" href="/#streams">streams page</a>', str(result.content))
def test_html_settings_links_help_docs(self) -> None:
result = self.client_get('/help/change-the-date-and-time-format')
self.assertIn('click <a href="/#settings/display-settings">Display settings</a>', str(result.content))
self.assertEqual(result.status_code, 200)
with self.settings(ROOT_DOMAIN_LANDING_PAGE=True):
result = self.client_get('/help/change-the-date-and-time-format',
subdomain="")
self.assertEqual(result.status_code, 200)
self.assertIn('<strong>Display settings</strong>', str(result.content))
self.assertNotIn('click <a href="/#settings/display-settings">Display settings</a>', str(result.content))
class IntegrationTest(TestCase):
def test_check_if_every_integration_has_logo_that_exists(self) -> None:
for integration in INTEGRATIONS.values():