') ret = re.sub(r'
\n((?:\n)*)(?:\{\.quote(\w+)\})', r'
\n\g<1>', ret, flags=re.MULTILINE) return ret def _convert_with_pandoc(mdwn, inputfmt='markdown', outputfmt='html5', ext_enabled=None, ext_disabled=None, standalone=True, title="HTML E-Mail"): ''' Invoke pandoc to do the actual conversion of Markdown to HTML5. ''' if not ext_enabled: ext_enabled = [ 'backtick_code_blocks', 'line_blocks', 'fancy_lists', 'startnum', 'definition_lists', 'example_lists', 'table_captions', 'simple_tables', 'multiline_tables', 'grid_tables', 'pipe_tables', 'all_symbols_escapable', 'intraword_underscores', 'strikeout', 'superscript', 'subscript', 'fenced_divs', 'bracketed_spans', 'footnotes', 'inline_notes', 'emoji', 'tex_math_double_backslash', 'autolink_bare_uris' ] if not ext_disabled: ext_disabled = [ 'tex_math_single_backslash', 'tex_math_dollars', 'smart', 'raw_html' ] enabled = '+'.join(ext_enabled) disabled = '-'.join(ext_disabled) inputfmt = f'{inputfmt}+{enabled}-{disabled}' args = [] if standalone: args.append('--standalone') if title: args.append(f'--metadata=pagetitle:"{title}"') return pypandoc.convert_text(mdwn, format=inputfmt, to=outputfmt, extra_args=args) def _apply_styling(html): ''' Inline all styles defined and used into the individual HTML tags. ''' return pynliner.Pynliner().from_string(html).with_cssString(DEFAULT_CSS).run() def _postprocess_html(html): ''' Postprocess the generated and styled HTML. ''' return html def convert_markdown_to_html(mdwn): ''' Converts the input Markdown to HTML, handling separately the body, as well as an optional signature. ''' parts = re.split(r'^-- $', mdwn, 1, flags=re.MULTILINE) body = parts[0] if len(parts) == 2: sig = parts[1] else: sig = None html='' if body: body = _preprocess_markdown(body) body = _identify_quotes_for_later(body) html = _convert_with_pandoc(body, standalone=False) html = _reformat_quotes(html) if sig: sig = _preprocess_markdown(sig) html += SIGNATURE_HTML.format(sig='
'.join(sig.splitlines())) html = HTML_DOCUMENT.format(htmlbody=html) html = _apply_styling(html) html = _postprocess_html(html) return html def main(): ''' Convert text on stdin to HTML, and print it to stdout, like mutt would expect. ''' html = convert_markdown_to_html(sys.stdin.read()) if html: # mutt expects the content type in the first line, so: print(f'text/html\n\n{html}') if __name__ == '__main__': main()