Implement format=flowed and fix charset handling for text/plain
This commit is contained in:
parent
647e93afd5
commit
b1dbb3d40c
105
mbox2web
105
mbox2web
|
@ -130,11 +130,25 @@ partial_message_cache = {}
|
||||||
|
|
||||||
def render_body(msg, extra=None):
|
def render_body(msg, extra=None):
|
||||||
def render_text_plain(msg, extra=None):
|
def render_text_plain(msg, extra=None):
|
||||||
bodytmpl = jenv.get_template("body_text_plain.html")
|
# msg.get_charset() doesn't work
|
||||||
context = {
|
ct_params = dict(msg.get_params() or [])
|
||||||
"body": msg.get_payload(decode=True).decode(msg.get_charset() or "iso-8859-1")
|
charset = ct_params.get("charset", "iso-8859-1")
|
||||||
}
|
format = ct_params.get("format", "fixed")
|
||||||
return bodytmpl.render(context)
|
if format == "fixed":
|
||||||
|
bodytmpl = jenv.get_template("body_text_plain.html")
|
||||||
|
context = {
|
||||||
|
"body": msg.get_payload(decode=True).decode(charset)
|
||||||
|
}
|
||||||
|
return bodytmpl.render(context)
|
||||||
|
elif format == "flowed":
|
||||||
|
bodytmpl = jenv.get_template("body_text_plain_flowed.html")
|
||||||
|
parthtml = TextFlowedPart(msg).as_string()
|
||||||
|
context = {
|
||||||
|
"body": jinja2.Markup(parthtml),
|
||||||
|
}
|
||||||
|
return bodytmpl.render(context)
|
||||||
|
else:
|
||||||
|
raise NotImplementedError()
|
||||||
def render_multipart_mixed(msg, extra=None):
|
def render_multipart_mixed(msg, extra=None):
|
||||||
parts = msg.get_payload()
|
parts = msg.get_payload()
|
||||||
if type(parts) == str:
|
if type(parts) == str:
|
||||||
|
@ -627,6 +641,87 @@ class TextEnrichedPart:
|
||||||
return self.stack[0].as_string()
|
return self.stack[0].as_string()
|
||||||
|
|
||||||
|
|
||||||
|
class TextFlowedPart:
|
||||||
|
def __init__(self, msg):
|
||||||
|
self.quote_depth = 0
|
||||||
|
self.current_line = ""
|
||||||
|
self.flowed = False
|
||||||
|
self.lines = []
|
||||||
|
self.buffer_filled = False
|
||||||
|
|
||||||
|
ct_params = dict(msg.get_params())
|
||||||
|
charset = ct_params.get("charset", "iso-8859-1")
|
||||||
|
format = ct_params.get("format", "fixed")
|
||||||
|
delsp = ct_params.get("delsp", "no") == "yes"
|
||||||
|
raw_text = msg.get_payload(decode=True).decode(charset)
|
||||||
|
raw_lines = raw_text.split("\n")
|
||||||
|
|
||||||
|
for rl in raw_lines:
|
||||||
|
quote_depth = 0
|
||||||
|
while rl[:1] == ">":
|
||||||
|
quote_depth += 1
|
||||||
|
rl = rl[1:]
|
||||||
|
if rl[:1] == " ":
|
||||||
|
rl = rl[1:]
|
||||||
|
if rl == "-- ":
|
||||||
|
flowed = None
|
||||||
|
elif rl[-1:] == " ":
|
||||||
|
flowed = True
|
||||||
|
if delsp:
|
||||||
|
rl = rl[:-1]
|
||||||
|
else:
|
||||||
|
flowed = False
|
||||||
|
self.add_buffer(rl, quote_depth, flowed)
|
||||||
|
self.flush()
|
||||||
|
|
||||||
|
def add_buffer(self, line, quote_depth, flowed):
|
||||||
|
if flowed is None:
|
||||||
|
self.flush()
|
||||||
|
flowed = False
|
||||||
|
if quote_depth != self.quote_depth:
|
||||||
|
self.flush()
|
||||||
|
self.quote_depth = quote_depth
|
||||||
|
self.current_line += line
|
||||||
|
self.flowed |= flowed
|
||||||
|
self.buffer_filled = True
|
||||||
|
if not flowed:
|
||||||
|
self.flush()
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
if self.buffer_filled:
|
||||||
|
self.lines.append({
|
||||||
|
"quote_depth": self.quote_depth,
|
||||||
|
"flowed": self.flowed,
|
||||||
|
"content": self.current_line
|
||||||
|
})
|
||||||
|
self.current_line = ""
|
||||||
|
self.flowed = False
|
||||||
|
self.buffer_filled = False
|
||||||
|
|
||||||
|
def as_string(self):
|
||||||
|
prev_quote_depth = 0
|
||||||
|
s = ""
|
||||||
|
for ln in self.lines:
|
||||||
|
while ln["quote_depth"] > prev_quote_depth:
|
||||||
|
s += "<blockquote>\n"
|
||||||
|
prev_quote_depth += 1
|
||||||
|
while ln["quote_depth"] < prev_quote_depth:
|
||||||
|
s += "</blockquote>\n"
|
||||||
|
prev_quote_depth -= 1
|
||||||
|
if ln["flowed"]:
|
||||||
|
s += "<p class='flowed'>" + html.escape(ln["content"]) + "</p>\n"
|
||||||
|
else:
|
||||||
|
s += "<p class='fixed'>" + html.escape(ln["content"]) + "</p>\n"
|
||||||
|
while 0 < prev_quote_depth:
|
||||||
|
s += "</blockquote>"
|
||||||
|
prev_quote_depth -= 1
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for f in sys.argv[1:]:
|
for f in sys.argv[1:]:
|
||||||
print("F", f, file=sys.stderr)
|
print("F", f, file=sys.stderr)
|
||||||
mb = mailbox.mbox(f)
|
mb = mailbox.mbox(f)
|
||||||
|
|
|
@ -42,3 +42,23 @@ th {
|
||||||
.partinner.html {
|
.partinner.html {
|
||||||
max-width: 40rem;
|
max-width: 40rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.fixed {
|
||||||
|
font-family: monospace;
|
||||||
|
white-space: pre;
|
||||||
|
margin: 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.flowed {
|
||||||
|
font-family: monospace;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
max-width: 60em;
|
||||||
|
margin: 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text_plain_flowed blockquote {
|
||||||
|
border-left: solid 0.2em #004;
|
||||||
|
padding-left: 0.8em;
|
||||||
|
margin: 0em;
|
||||||
|
background: #EEF;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
<div class="partouter">
|
||||||
|
<div class="partheader">
|
||||||
|
text/plain
|
||||||
|
</div>
|
||||||
|
<div class="partinner text_plain_flowed">
|
||||||
|
{{body}}
|
||||||
|
</div>
|
||||||
|
</div>
|
Loading…
Reference in New Issue