diff options
-rw-r--r-- | default.html | 40 | ||||
-rw-r--r-- | html.c | 236 |
2 files changed, 108 insertions, 168 deletions
diff --git a/default.html b/default.html index f1503c4..8573ba6 100644 --- a/default.html +++ b/default.html @@ -9,12 +9,8 @@ body { padding: 0 1ch; } -nav ul { - padding: 0; - list-style-type: none; -} -nav ul li { - display: inline; +header { + margin: 1em 0; } main.index ol { @@ -46,39 +42,29 @@ article.message header h2 { font-size: 1em; margin: 0; } -article.message header nav ul { - margin: 0; -} - -ul.address { - padding: 0; - list-style-type: none; - display: inline; -} -ul.address li { - display: inline; -} pre { white-space: pre-wrap; } -pre q::before, pre q::after { - content: none; -} -pre q { +span.quote { color: navy; } -pre q q { +span.quote.level2 { color: teal; } -pre q q q { +span.quote.level3 { color: purple; } -pre del { - text-decoration: none; +span.diff.head { + font-weight: bold; +} +span.diff.hunk { + color: navy; +} +span.diff.old { color: red; } -pre ins { +span.diff.new { text-decoration: none; color: green; } diff --git a/html.c b/html.c index 95afe4d..1757fd9 100644 --- a/html.c +++ b/html.c @@ -46,29 +46,21 @@ static char *htmlMailto(struct Address addr) { return templateString("mailto:[mailbox]@[host]", vars, escapeURL); } -static int htmlAddress(FILE *file, struct Address addr, bool last) { +static int htmlAddress(FILE *file, struct Address addr, bool comma) { char *mailto = htmlMailto(addr); const char *template; if (addr.host) { - template = Q( - <li><a href="[mailto]">[name]</a>[,]</li> - ); + template = Q([,]<a href="[mailto]">[name]</a>); } else if (addr.mailbox) { - template = Q( - <li>[mailbox]: - <ul> - ); + template = "[mailbox]: "; } else { - template = Q( - </ul>; - </li> - ); + template = ";"; } struct Variable vars[] = { { "mailto", mailto }, { "name", addressName(addr) }, { "mailbox", addr.mailbox }, - { ",", (last ? "" : ", ") }, + { ",", (comma ? ", " : " ") }, {0}, }; int error = templateRender(file, template, vars, escapeXML); @@ -82,7 +74,6 @@ htmlAddressList(FILE *file, const char *name, struct AddressList list) { const char *template = Q( <div class="[name]"> [name]: - <ul class="address"> ); struct Variable vars[] = { { "name", name }, @@ -91,31 +82,12 @@ htmlAddressList(FILE *file, const char *name, struct AddressList list) { int error = templateRender(file, template, vars, escapeXML); if (error) return error; for (size_t i = 0; i < list.len; ++i) { - error = htmlAddress(file, list.addrs[i], i == list.len - 1); + error = htmlAddress( + file, list.addrs[i], i > 0 && list.addrs[i - 1].host + ); if (error) return error; } - return templateRender(file, Q(</ul></div>), NULL, NULL); -} - -static char *htmlReply(const struct Envelope *envelope) { - const char *template = { - "mailto:[mailbox]@[host]" - "?cc=[cc]" - "&subject=[re][subject]" - "&In-Reply-To=[<][messageID][>]" - }; - struct Variable vars[] = { - { "mailbox", envelope->replyTo.mailbox }, - { "host", envelope->replyTo.host }, - { "cc", baseMailto }, - { "re", (strncmp(envelope->subject, "Re: ", 4) ? "Re: " : "") }, - { "subject", envelope->subject }, - { "messageID", envelope->messageID }, - { "<", "<" }, - { ">", ">" }, - {0}, - }; - return templateString(template, vars, escapeURL); + return templateRender(file, Q(</div>), NULL, NULL); } static char *htmlFragment(const char *messageID) { @@ -135,35 +107,50 @@ static char *htmlMbox(const char *messageID) { return templateString("../" PATH_MESSAGE, vars, escapeURL); } -static int -htmlNavItem(FILE *file, const char *name, const char *base, const char *url) { - const char *template = Q(<li><a href="[base][url]">[name]</a> </li>); +static char *htmlReply(const struct Envelope *envelope) { + const char *template = { + "mailto:[mailbox]@[host]" + "?cc=[cc]" + "&subject=[re][subject]" + "&In-Reply-To=[<][messageID][>]" + }; struct Variable vars[] = { - { "name", name }, - { "base", base }, - { "url", url }, + { "mailbox", envelope->replyTo.mailbox }, + { "host", envelope->replyTo.host }, + { "cc", baseMailto }, + { "re", (strncmp(envelope->subject, "Re: ", 4) ? "Re: " : "") }, + { "subject", envelope->subject }, + { "messageID", envelope->messageID }, + { "<", "<" }, + { ">", ">" }, {0}, }; - return templateRender(file, template, vars, escapeXML); -} - -static int htmlParent(FILE *file, const struct Envelope *envelope) { - if (!envelope->inReplyTo) return 0; - char *fragment = htmlFragment(envelope->inReplyTo); - int error = htmlNavItem(file, "parent", "", fragment); - free(fragment); - return error; + return templateString(template, vars, escapeURL); } int htmlMessageNav(FILE *file, const struct Envelope *envelope) { + char *parent = envelope->inReplyTo + ? htmlFragment(envelope->inReplyTo) + : NULL; char *mbox = htmlMbox(envelope->messageID); char *reply = htmlReply(envelope); - int error = 0 - || templateRender(file, Q(<nav><ul>), NULL, NULL) - || htmlParent(file, envelope) - || htmlNavItem(file, "download", "", mbox) - || htmlNavItem(file, "reply", "", reply) - || templateRender(file, Q(</ul></nav>), NULL, NULL); + const char *template = Q( + <nav> + [+parent] + <a href="[parent]">parent</a> + [-] + <a href="[mbox]">download</a> + <a href="[reply]">reply</a> + </nav> + ); + struct Variable vars[] = { + { "parent", parent }, + { "mbox", mbox }, + { "reply", reply }, + {0}, + }; + int error = templateRender(file, template, vars, escapeXML); + free(parent); free(mbox); free(reply); return error; @@ -202,43 +189,6 @@ int htmlMessageOpen(FILE *file, const struct Envelope *envelope) { return error; } -static int htmlInlineAttrs(FILE *file, const struct BodyPart *part) { - const char *template = " " Q([attr]="[value]"); - if (part->contentID) { - struct Variable vars[] = { - { "attr", "id" }, - { "value", part->contentID }, - {0}, - }; - int error = templateRender(file, template, vars, escapeXML); - if (error) return error; - } - if (part->description) { - struct Variable vars[] = { - { "attr", "title" }, - { "value", part->description }, - {0}, - }; - int error = templateRender(file, template, vars, escapeXML); - if (error) return error; - } - const char *language = NULL; - if (part->language.type == String) language = part->language.string; - if (part->language.type == List && part->language.list.len == 1) { - language = dataCheck(part->language.list.ptr[0], String).string; - } - if (language) { - struct Variable vars[] = { - { "attr", "lang" }, - { "value", language }, - {0}, - }; - int error = templateRender(file, template, vars, escapeXML); - if (error) return error; - } - return 0; -} - static void swap(char *a, char *b) { char ch = *a; *a = *b; @@ -278,20 +228,17 @@ static int htmlMarkupURLs(FILE *file, char *buf) { } static int htmlMarkupQuote(FILE *file, char *buf) { - int error; - size_t level = 0; + uint32_t level = 0; for (char *ch = buf; *ch == '>' || *ch == ' '; level += (*ch++ == '>')); - for (size_t i = 0; i < level; ++i) { - error = templateRender(file, Q(<q>), NULL, NULL); - if (error) return error; - } - error = htmlMarkupURLs(file, buf); - if (error) return error; - for (size_t i = 0; i < level; ++i) { - error = templateRender(file, Q(</q>), NULL, NULL); - if (error) return error; - } - return 0; + const char *template = Q(<span class="quote level[level]">); + struct Variable vars[] = { + { "level", u32(level).s }, + {0}, + }; + return 0 + || templateRender(file, template, vars, escapeXML) + || htmlMarkupURLs(file, buf) + || templateRender(file, Q(</span>), NULL, NULL); } static int htmlMarkup(FILE *file, const char *content) { @@ -319,7 +266,7 @@ static int htmlMarkup(FILE *file, const char *content) { patch = false; } - static const char *Pattern = "^(diff|index|---|[+]{3}|@@) "; + static const char *Pattern = "^(diff|index|---|[+]{3}) "; static regex_t regex; if (!regex.re_nsub) { error = regcomp(®ex, Pattern, REG_EXTENDED); @@ -327,15 +274,19 @@ static int htmlMarkup(FILE *file, const char *content) { } if (patch && !regexec(®ex, buf, 0, NULL, 0)) { error = templateRender( - file, Q(<b>[line]</b>), vars, escapeXML + file, Q(<span class="diff head">[line]</span>), vars, escapeXML + ); + } else if (patch && buf[0] == '@' && buf[1] == '@') { + error = templateRender( + file, Q(<span class="diff hunk">[line]</span>), vars, escapeXML ); } else if (patch && buf[0] == '-' && strcmp(buf, "---")) { error = templateRender( - file, Q(<del>[line]</del>), vars, escapeXML + file, Q(<span class="diff old">[line]</span>), vars, escapeXML ); } else if (patch && buf[0] == '+') { error = templateRender( - file, Q(<ins>[line]</ins>), vars, escapeXML + file, Q(<span class="diff new">[line]</span>), vars, escapeXML ); } else if (patch) { error = escapeXML(file, buf); @@ -354,10 +305,25 @@ static int htmlMarkup(FILE *file, const char *content) { } int htmlInline(FILE *file, const struct BodyPart *part, const char *content) { + const char *template = Q( + <pre + [+contentID]id="[contentID]"[-] + [+description]title="[description]"[-] + [+language]lang="[language]"[-]> + ); + const char *language = NULL; + if (part->language.type == String) language = part->language.string; + if (part->language.type == List && part->language.list.len == 1) { + language = dataCheck(part->language.list.ptr[0], String).string; + } + struct Variable vars[] = { + { "contentID", part->contentID }, + { "description", part->description }, + { "language", language }, + {0}, + }; return 0 - || templateRender(file, Q(<pre), NULL, NULL) - || htmlInlineAttrs(file, part) - || templateRender(file, Q(>), NULL, NULL) + || templateRender(file, template, vars, escapeXML) || htmlMarkup(file, content) || templateRender(file, Q(</pre>), NULL, NULL); } @@ -436,11 +402,9 @@ int htmlThreadOpen(FILE *file, const struct Envelope *envelope) { <header class="thread"> <h1>[subject]</h1> <nav> - <ul> - <li><a href="../index.html">index</a> </li> - <li><a href="[atom]">follow</a> </li> - <li><a href="[mbox]">download</a> </li> - </ul> + <a href="../index.html">index</a> + <a href="[atom]">follow</a> + <a href="[mbox]">download</a> </nav> </header> <main class="thread"> @@ -533,38 +497,28 @@ int htmlIndexHead(FILE *file) { return templateRender(file, template, vars, escapeXML); } -static int htmlIndexNav(FILE *file) { - int error = 0 - || templateRender(file, Q(<nav><ul>), NULL, NULL) - || htmlNavItem(file, "follow", "", "index.atom"); - if (error) return error; - if (baseSubscribe) { - error = htmlNavItem(file, "subscribe", "", baseSubscribe); - if (error) return error; - } - return 0 - || htmlNavItem(file, "write", "mailto:", baseMailto) - || templateRender(file, Q(</ul></nav>), NULL, NULL); -} - int htmlIndexOpen(FILE *file) { - const char *head = Q( + const char *template = Q( <header class="index"> <h1>[title]</h1> - ); - const char *tail = Q( + <nav> + <a href="index.atom">follow</a> + [+subscribe] + <a href="[subscribe]">subscribe</a> + [-] + <a href="mailto:[mailto]">write</a> + </nav> </header> <main class="index"> <ol> ); struct Variable vars[] = { { "title", baseTitle }, + { "subscribe", baseSubscribe }, + { "mailto", baseMailto }, {0}, }; - return 0 - || templateRender(file, head, vars, escapeXML) - || htmlIndexNav(file) - || templateRender(file, tail, vars, escapeXML); + return templateRender(file, template, vars, escapeXML); } static char *htmlIndexURL(const struct Envelope *envelope) { |