X-Git-Url: https://git.madduck.net/etc/mutt.git/blobdiff_plain/e90ca40d33d14a23aae53b74f9b35b37637d0c01..a83d50d5a64488deb3796bbd0ca0a03b0516cc77:/.mutt/markdown2html?ds=sidebyside
diff --git a/.mutt/markdown2html b/.mutt/markdown2html
index e3c2b30..487d3db 100755
--- a/.mutt/markdown2html
+++ b/.mutt/markdown2html
@@ -48,20 +48,24 @@ except ImportError:
DEFAULT_CSS += '''
-.quote {
+.block {
+ padding: 0 0.5em;
+ margin: 0;
+ border-left: 2px solid #eee;
+}
+.quote, blockquote {
padding: 0 0.5em;
margin: 0;
font-style: italic;
- border-left: 2px solid #ccc;
- color: #999;
+ border-left: 2px solid #666;
+ color: #666;
font-size: 80%;
}
.quotelead {
- font-style: italic;
margin-bottom: -1em;
- color: #999;
font-size: 80%;
}
+.quotechar { display: none; }
.footnote-ref, .footnote-back { text-decoration: none;}
.signature {
color: #999;
@@ -69,28 +73,46 @@ DEFAULT_CSS += '''
white-space: pre;
margin: 1em 0 0 0;
font-size: 80%;
-}'''
+}
+table, th, td {
+ border-collapse: collapse;
+ border: 1px solid #999;
+}
+th, td { padding: 0.5em; }
+.header {
+ background: #eee;
+}
+.even { background: #eee; }
+h1, h2, h3, h4, h5, h6 {
+ color: #666;
+ background-color: #eee;
+ padding-left: 0.5em
+}
+h1 { font-size: 130%; }
+h2 { font-size: 120%; }
+h3 { font-size: 110%; }
+h4 { font-size: 107%; }
+h5 { font-size: 103%; }
+h6 { font-size: 100%; }
+p { padding: 0 0.5em; }
+pre { padding: 0 1em; }
+'''
STYLESHEET = os.path.join(os.path.expanduser('~/.mutt'),
'markdown2html.css')
if os.path.exists(STYLESHEET):
DEFAULT_CSS += open(STYLESHEET).read()
-HTML_DOCUMENT = '''
-
-
-
-
-HTML E-Mail
-
-{htmlbody}
-'''
-
-
SIGNATURE_HTML = \
'-- {sig}
'
+def _preprocess_signature(sig):
+ '''
+ Preprocess the signature before markdown processing.
+ '''
+ return sig
+
def _preprocess_markdown(mdwn):
'''
Preprocess Markdown for handling by the converter.
@@ -100,6 +122,21 @@ def _preprocess_markdown(mdwn):
# regexp will not match between paragraphs.
ret = re.sub(r'(\S)\n(\s*\S)', r'\g<1> \n\g<2>', mdwn, flags=re.MULTILINE)
+ # Clients like Thunderbird need the leading '>' to be able to properly
+ # create nested quotes, so we duplicate the symbol, the first instance
+ # will tell pandoc to create a blockquote, while the second instance will
+ # be a containing the character, along with a class that causes CSS
+ # to actually hide it from display. However, this does not work with the
+ # text-mode HTML2text converters, and so it's left commented for now.
+ #ret = re.sub(r'\n>', r' \n>[>]{.quotechar}', ret, flags=re.MULTILINE)
+
+ # With the autolink_bare_uris extension, we do not need to put links into
+ # angle brackets to have them converted, so let's conserve the brackets
+ # when used around email addresses. Note that this needs a postprocessing
+ # hack because the pandoc autolink converted includes the ambersand
+ # (https://github.com/jgm/pandoc/issues/7398).
+ ret = re.sub(r'<([^@]+@.+\.[^>]+)>', r'<\g<1> -PANDOC_BUG_7398->', ret)
+
return ret
@@ -141,7 +178,7 @@ def _identify_quotes_for_later(mdwn):
# The lead-in to a quote is a single line immediately preceding the
# quote, and ending with ':'. Note that there could be multiple of
# these:
- if re.match(r'^.+:\s*$', cur) and nxt.startswith('>'):
+ if re.match(r'^[^>]+.*:\s*$', cur) and nxt.startswith('>'):
ret.append(f'{{.quotelead}}{cur.strip()}')
# pandoc needs an empty line before the blockquote, so
# we enter one for the purpose of HTML rendition:
@@ -150,13 +187,13 @@ def _identify_quotes_for_later(mdwn):
# The first blockquote after such a lead-in gets marked as the
# "initial" quote:
- elif prev and re.match(r'^.+:\s*$', prev) and cur.startswith('>'):
+ elif prev and re.match(r'^[^>]+.*:\s*$', prev) and cur.startswith('>'):
ret.append(re.sub(r'^(\s*>\s*)+(.+)',
r'\g<1>{.quoteinitial}\g<2>',
cur, flags=re.MULTILINE))
# All other occurrences of blockquotes get the "subsequent" marker:
- elif cur.startswith('>') and prev and not prev.startswith('>'):
+ elif cur.startswith('>') and prev is not None and not prev.startswith('>'):
ret.append(re.sub(r'^((?:\s*>\s*)+)(.+)',
r'\g<1>{.quotesubsequent}\g<2>',
cur, flags=re.MULTILINE))
@@ -181,7 +218,7 @@ def _reformat_quotes(html):
def _convert_with_pandoc(mdwn, inputfmt='markdown', outputfmt='html5',
ext_enabled=None, ext_disabled=None,
- standalone=True, title="HTML E-Mail"):
+ standalone=True, selfcontained=True, title=None):
'''
Invoke pandoc to do the actual conversion of Markdown to HTML5.
'''
@@ -208,10 +245,12 @@ def _convert_with_pandoc(mdwn, inputfmt='markdown', outputfmt='html5',
'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'
]
@@ -222,6 +261,8 @@ def _convert_with_pandoc(mdwn, inputfmt='markdown', outputfmt='html5',
args = []
if standalone:
args.append('--standalone')
+ if selfcontained:
+ args.append('--self-contained')
if title:
args.append(f'--metadata=pagetitle:"{title}"')
@@ -240,6 +281,10 @@ def _postprocess_html(html):
'''
Postprocess the generated and styled HTML.
'''
+
+ # Preprocessing leaves a sentinel to work around
+ # https://github.com/jgm/pandoc/issues/7398, and so we need to remove it:
+ html = html.replace(' -PANDOC_BUG_7398->', '>')
return html
@@ -259,14 +304,19 @@ def convert_markdown_to_html(mdwn):
if body:
body = _preprocess_markdown(body)
body = _identify_quotes_for_later(body)
- html = _convert_with_pandoc(body, standalone=False)
+ html = _convert_with_pandoc(body, standalone=True, selfcontained=True,
+ title=None)
+ html = html.replace('Untitled\n','')
html = _reformat_quotes(html)
if sig:
+ sig = _preprocess_signature(sig)
sig = _preprocess_markdown(sig)
- html += SIGNATURE_HTML.format(sig='
'.join(sig.splitlines()))
+ sig = _convert_with_pandoc(sig, standalone=False, selfcontained=False)
+ sig = SIGNATURE_HTML.format(sig='
'.join(sig.splitlines()))
+ eob = html.find('