def render_markdown_path(markdown_file_path: str, context: Optional[Dict[Any, Any]]=None) -> str: """Given a path to a markdown file, return the rendered html. 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: md_extensions = [ markdown.extensions.extra.makeExtension(), markdown.extensions.toc.makeExtension(), markdown.extensions.admonition.makeExtension(), markdown.extensions.codehilite.makeExtension( linenums=False, guess_lang=False ), zerver.lib.bugdown.fenced_code.makeExtension(), zerver.lib.bugdown.api_arguments_table_generator.makeExtension( base_path='templates/zerver/api/'), zerver.lib.bugdown.api_code_examples.makeExtension(), zerver.lib.bugdown.nested_code_blocks.makeExtension(), zerver.lib.bugdown.help_settings_links.makeExtension(), ] if md_macro_extension is None: md_macro_extension = markdown_include.include.makeExtension( base_path='templates/zerver/help/include/') if any(doc in markdown_file_path for doc in docs_without_macros): md_engine = markdown.Markdown(extensions=md_extensions) else: md_engine = markdown.Markdown(extensions=md_extensions + [md_macro_extension]) md_engine.reset() jinja = engines['Jinja2'] markdown_string = jinja.env.loader.get_source(jinja.env, markdown_file_path)[0] html = md_engine.convert(markdown_string) html_template = jinja.from_string(html) return mark_safe(html_template.render(context))
def render_markdown_path(markdown_file_path: str, context: Optional[Dict[Any, Any]] = None, pure_markdown: Optional[bool] = False) -> str: """Given a path to a markdown file, return the rendered html. 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'))) from zerver.lib.bugdown.help_relative_links import set_relative_help_links set_relative_help_links(bool(context.get('html_settings_links'))) global md_extensions global md_macro_extension if md_extensions is None: md_extensions = [ markdown.extensions.extra.makeExtension(), markdown.extensions.toc.makeExtension(), markdown.extensions.admonition.makeExtension(), markdown.extensions.codehilite.makeExtension(linenums=False, guess_lang=False), zerver.lib.bugdown.fenced_code.makeExtension(), zerver.lib.bugdown.api_arguments_table_generator.makeExtension( base_path='templates/zerver/api/'), zerver.lib.bugdown.api_code_examples.makeExtension(), zerver.lib.bugdown.nested_code_blocks.makeExtension(), zerver.lib.bugdown.tabbed_sections.makeExtension(), zerver.lib.bugdown.help_settings_links.makeExtension(), zerver.lib.bugdown.help_relative_links.makeExtension(), zerver.lib.bugdown.help_emoticon_translations_table.makeExtension( ), ] if md_macro_extension is None: md_macro_extension = markdown_include.include.makeExtension( base_path='templates/zerver/help/include/') if any(doc in markdown_file_path for doc in docs_without_macros): md_engine = markdown.Markdown(extensions=md_extensions) else: md_engine = markdown.Markdown(extensions=md_extensions + [md_macro_extension]) md_engine.reset() jinja = engines['Jinja2'] try: # By default, we do both Jinja2 templating and markdown # processing on the file, to make it easy to use both Jinja2 # context variables and markdown includes in the file. markdown_string = jinja.env.loader.get_source(jinja.env, markdown_file_path)[0] except TemplateNotFound as e: if pure_markdown: # For files such as /etc/zulip/terms.md where we don't intend # to use Jinja2 template variables, we still try to load the # template using Jinja2 (in case the file path isn't absolute # and does happen to be in Jinja's recognized template # directories), and if that fails, we try to load it directly # from disk. with open(markdown_file_path) as fp: markdown_string = fp.read() else: raise e html = md_engine.convert(markdown_string) rendered_html = jinja.from_string(html).render(context) if context.get('unescape_rendered_html', False): # In some exceptional cases (such as our Freshdesk webhook docs), # code blocks in some of our Markdown templates have characters such # as '{' encoded as '{' to prevent clashes with Jinja2 syntax, # but the encoded form never gets decoded because the text ends up # inside a <pre> tag. So here, we explicitly "unescape" such characters # if 'unescape_rendered_html' is True. rendered_html = unescape(rendered_html) return mark_safe(rendered_html)
def render_markdown_path(markdown_file_path: str, context: Optional[Dict[Any, Any]]=None, pure_markdown: Optional[bool]=False) -> str: """Given a path to a markdown file, return the rendered html. 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: md_extensions = [ markdown.extensions.extra.makeExtension(), markdown.extensions.toc.makeExtension(), markdown.extensions.admonition.makeExtension(), markdown.extensions.codehilite.makeExtension( linenums=False, guess_lang=False ), zerver.lib.bugdown.fenced_code.makeExtension(), zerver.lib.bugdown.api_arguments_table_generator.makeExtension( base_path='templates/zerver/api/'), zerver.lib.bugdown.api_code_examples.makeExtension(), zerver.lib.bugdown.nested_code_blocks.makeExtension(), zerver.lib.bugdown.help_settings_links.makeExtension(), zerver.lib.bugdown.help_emoticon_translations_table.makeExtension(), ] if md_macro_extension is None: md_macro_extension = markdown_include.include.makeExtension( base_path='templates/zerver/help/include/') if any(doc in markdown_file_path for doc in docs_without_macros): md_engine = markdown.Markdown(extensions=md_extensions) else: md_engine = markdown.Markdown(extensions=md_extensions + [md_macro_extension]) md_engine.reset() jinja = engines['Jinja2'] try: # By default, we do both Jinja2 templating and markdown # processing on the file, to make it easy to use both Jinja2 # context variables and markdown includes in the file. markdown_string = jinja.env.loader.get_source(jinja.env, markdown_file_path)[0] except TemplateNotFound as e: if pure_markdown: # For files such as /etc/zulip/terms.md where we don't intend # to use Jinja2 template variables, we still try to load the # template using Jinja2 (in case the file path isn't absolute # and does happen to be in Jinja's recognized template # directories), and if that fails, we try to load it directly # from disk. with open(markdown_file_path) as fp: markdown_string = fp.read() else: raise e html = md_engine.convert(markdown_string) rendered_html = jinja.from_string(html).render(context) if context.get('unescape_rendered_html', False): # In some exceptional cases (such as our Freshdesk webhook docs), # code blocks in some of our Markdown templates have characters such # as '{' encoded as '{' to prevent clashes with Jinja2 syntax, # but the encoded form never gets decoded because the text ends up # inside a <pre> tag. So here, we explicitly "unescape" such characters # if 'unescape_rendered_html' is True. rendered_html = unescape(rendered_html) return mark_safe(rendered_html)
def render_markdown_path(markdown_file_path: str, context: Mapping[str, Any] = {}, pure_markdown: bool = False) -> str: """Given a path to a markdown file, return the rendered html. Note that this assumes that any HTML in the markdown file is trusted; it is intended to be used for documentation, not user data.""" # 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'))) from zerver.lib.bugdown.help_relative_links import set_relative_help_links set_relative_help_links(bool(context.get('html_settings_links'))) global md_extensions global md_macro_extension if md_extensions is None: md_extensions = [ markdown.extensions.extra.makeExtension(), markdown.extensions.toc.makeExtension(), markdown.extensions.admonition.makeExtension(), markdown.extensions.codehilite.makeExtension( linenums=False, guess_lang=False, ), zerver.lib.bugdown.fenced_code.makeExtension( run_content_validators=context.get('run_content_validators', False), ), zerver.lib.bugdown.api_arguments_table_generator.makeExtension( base_path='templates/zerver/api/'), zerver.lib.bugdown.api_return_values_table_generator.makeExtension( base_path='templates/zerver/api/'), zerver.lib.bugdown.nested_code_blocks.makeExtension(), zerver.lib.bugdown.tabbed_sections.makeExtension(), zerver.lib.bugdown.help_settings_links.makeExtension(), zerver.lib.bugdown.help_relative_links.makeExtension(), zerver.lib.bugdown.help_emoticon_translations_table.makeExtension( ), ] if md_macro_extension is None: md_macro_extension = zerver.lib.bugdown.include.makeExtension( base_path='templates/zerver/help/include/') extensions = md_extensions if 'api_url' in context: # We need to generate the API code examples extension each # time so the `api_url` config parameter can be set dynamically. # # TODO: Convert this to something more efficient involving # passing the API URL as a direct parameter. extensions = extensions + [ zerver.openapi.markdown_extension.makeExtension( api_url=context["api_url"], ) ] if not any(doc in markdown_file_path for doc in docs_without_macros): extensions = extensions + [md_macro_extension] md_engine = markdown.Markdown(extensions=extensions) md_engine.reset() jinja = engines['Jinja2'] try: # By default, we do both Jinja2 templating and markdown # processing on the file, to make it easy to use both Jinja2 # context variables and markdown includes in the file. markdown_string = jinja.env.loader.get_source(jinja.env, markdown_file_path)[0] except TemplateNotFound as e: if pure_markdown: # For files such as /etc/zulip/terms.md where we don't intend # to use Jinja2 template variables, we still try to load the # template using Jinja2 (in case the file path isn't absolute # and does happen to be in Jinja's recognized template # directories), and if that fails, we try to load it directly # from disk. with open(markdown_file_path) as fp: markdown_string = fp.read() else: raise e html = md_engine.convert(markdown_string) rendered_html = jinja.from_string(html).render(context) return mark_safe(rendered_html)