Implement format=flowed and fix charset handling for text/plain
This commit is contained in:
parent
647e93afd5
commit
b1dbb3d40c
97
mbox2web
97
mbox2web
|
@ -130,11 +130,25 @@ partial_message_cache = {}
|
|||
|
||||
def render_body(msg, extra=None):
|
||||
def render_text_plain(msg, extra=None):
|
||||
# msg.get_charset() doesn't work
|
||||
ct_params = dict(msg.get_params() or [])
|
||||
charset = ct_params.get("charset", "iso-8859-1")
|
||||
format = ct_params.get("format", "fixed")
|
||||
if format == "fixed":
|
||||
bodytmpl = jenv.get_template("body_text_plain.html")
|
||||
context = {
|
||||
"body": msg.get_payload(decode=True).decode(msg.get_charset() or "iso-8859-1")
|
||||
"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):
|
||||
parts = msg.get_payload()
|
||||
if type(parts) == str:
|
||||
|
@ -627,6 +641,87 @@ class TextEnrichedPart:
|
|||
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:]:
|
||||
print("F", f, file=sys.stderr)
|
||||
mb = mailbox.mbox(f)
|
||||
|
|
|
@ -42,3 +42,23 @@ th {
|
|||
.partinner.html {
|
||||
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