diff options
-rw-r--r-- | archive.h | 4 | ||||
-rw-r--r-- | atom.c | 90 | ||||
-rw-r--r-- | default.html | 3 | ||||
-rw-r--r-- | html.c | 220 |
4 files changed, 156 insertions, 161 deletions
diff --git a/archive.h b/archive.h index 75d8781..f0bda03 100644 --- a/archive.h +++ b/archive.h @@ -26,6 +26,8 @@ #define GENERATOR_URL "https://git.causal.agency/bubger" +#define Q(...) #__VA_ARGS__ + struct Address { char *name; const char *mailbox; @@ -159,8 +161,6 @@ void concatData( void concatThreads(struct List threads, const struct Envelope *envelopes); void concatIndex(struct List threads, const struct Envelope *envelopes); -#define TEMPLATE(...) #__VA_ARGS__ - struct Variable { const char *name; const char *value; diff --git a/atom.c b/atom.c index 7bc4fe9..35cc840 100644 --- a/atom.c +++ b/atom.c @@ -31,12 +31,12 @@ static char *atomID(const struct Envelope *envelope) { } static int atomAuthor(FILE *file, struct Address addr) { - const char *template = TEMPLATE( - <author> - <name>[name]</name> - <email>[mailbox]@[host]</email> - </author> - ); + const char *template = { + Q(<author>) + Q(<name>[name]</name>) + Q(<email>[mailbox]@[host]</email>) + Q(</author>) + }; struct Variable vars[] = { { "name", addressName(addr) }, { "mailbox", addr.mailbox }, @@ -62,13 +62,13 @@ static const char *atomUpdated(time_t time) { } int atomEntryOpen(FILE *file, const struct Envelope *envelope) { - const char *template = TEMPLATE( - <entry> - <id>[id]</id> - <title>[title]</title> - <updated>[updated]</updated> - <link rel="alternate" type="application/mbox" href="[base][url]"/> - ); + const char *template = { + Q(<entry>) + Q(<id>[id]</id>) + Q(<title>[title]</title>) + Q(<updated>[updated]</updated>) + Q(<link rel="alternate" type="application/mbox" href="[base][url]"/>) + }; char *id = atomID(envelope); char *url = atomEntryURL(envelope); struct Variable vars[] = { @@ -88,13 +88,13 @@ int atomEntryOpen(FILE *file, const struct Envelope *envelope) { } int atomContent(FILE *file, const char *content) { - const char *template = TEMPLATE( - <content type="xhtml"> - <div xmlns="http://www.w3.org/1999/xhtml"> - <pre>[content]</pre> - </div> - </content> - ); + const char *template = { + Q(<content type="xhtml">) + Q(<div xmlns="http://www.w3.org/1999/xhtml">) + Q(<pre>[content]</pre>) + Q(</div>) + Q(</content>) + }; struct Variable vars[] = { { "content", content }, {0}, @@ -103,7 +103,7 @@ int atomContent(FILE *file, const char *content) { } int atomEntryClose(FILE *file) { - return templateRender(file, TEMPLATE(</entry>), NULL, NULL); + return templateRender(file, Q(</entry>), NULL, NULL); } static char *atomThreadURL(const struct Envelope *envelope, const char *type) { @@ -116,23 +116,22 @@ static char *atomThreadURL(const struct Envelope *envelope, const char *type) { } int atomThreadOpen(FILE *file, const struct Envelope *envelope) { - const char *template = TEMPLATE( - <[q]xml version="1.0" encoding="utf-8"[q]> - <feed xmlns="http://www.w3.org/2005/Atom"> - <generator uri="[generator]">bubger</generator> - <id>[id]</id> - <title>[title]</title> - <updated>[updated]</updated> - <link rel="self" href="[base][atom]"/> - <link rel="alternate" type="text/html" href="[base][html]"/> - <link rel="alternate" type="application/mbox" href="[base][mbox]"/> - ); + const char *template = { + "<?" Q(xml version="1.0" encoding="utf-8") "?>" + Q(<feed xmlns="http://www.w3.org/2005/Atom">) + Q(<generator uri="[generator]">bubger</generator>) + Q(<id>[id]</id>) + Q(<title>[title]</title>) + Q(<updated>[updated]</updated>) + Q(<link rel="self" href="[base][atom]"/>) + Q(<link rel="alternate" type="text/html" href="[base][html]"/>) + Q(<link rel="alternate" type="application/mbox" href="[base][mbox]"/>) + }; char *id = atomID(envelope); char *atom = atomThreadURL(envelope, "atom"); char *html = atomThreadURL(envelope, "html"); char *mbox = atomThreadURL(envelope, "mbox"); struct Variable vars[] = { - { "q", "?" }, { "generator", GENERATOR_URL }, { "id", id }, { "title", envelope->subject }, @@ -154,22 +153,21 @@ int atomThreadOpen(FILE *file, const struct Envelope *envelope) { } int atomThreadClose(FILE *file) { - return templateRender(file, TEMPLATE(</feed>), NULL, NULL); + return templateRender(file, Q(</feed>), NULL, NULL); } int atomIndexOpen(FILE *file) { - const char *template = TEMPLATE( - <[q]xml version="1.0" encoding="utf-8"[q]> - <feed xmlns="http://www.w3.org/2005/Atom"> - <generator uri="[generator]">bubger</generator> - <id>mailto:[mailto]</id> - <title>[title]</title> - <updated>[updated]</updated> - <link rel="self" href="[base]/index.atom"/> - <link rel="alternate" type="text/html" href="[base]/index.html"/> - ); + const char *template = { + "<?" Q(xml version="1.0" encoding="utf-8") "?>" + Q(<feed xmlns="http://www.w3.org/2005/Atom">) + Q(<generator uri="[generator]">bubger</generator>) + Q(<id>mailto:[mailto]</id>) + Q(<title>[title]</title>) + Q(<updated>[updated]</updated>) + Q(<link rel="self" href="[base]/index.atom"/>) + Q(<link rel="alternate" type="text/html" href="[base]/index.html"/>) + }; struct Variable vars[] = { - { "q", "?" }, { "generator", GENERATOR_URL }, { "mailto", baseMailto }, { "title", baseTitle }, @@ -181,5 +179,5 @@ int atomIndexOpen(FILE *file) { } int atomIndexClose(FILE *file) { - return templateRender(file, TEMPLATE(</feed>), NULL, NULL); + return templateRender(file, Q(</feed>), NULL, NULL); } diff --git a/default.html b/default.html index 6ff49cf..36736a6 100644 --- a/default.html +++ b/default.html @@ -80,6 +80,9 @@ ul.recipient li.group::after { address.from::before { content: 'From: '; } +address.from { + margin-right: 1ch; +} ul.to::before { content: 'To: '; margin-right: 1ch; diff --git a/html.c b/html.c index 215c208..0d086da 100644 --- a/html.c +++ b/html.c @@ -28,20 +28,18 @@ static int htmlAddress(FILE *file, const char *class, struct Address addr) { const char *template; if (addr.host) { - template = TEMPLATE( - <li><address class="[class]">[name]</address></li> - ); + template = Q(<li><address class="[class]">[name]</address></li>); } else if (addr.mailbox) { - template = TEMPLATE( - <li class="group"> - <address class="[class]">[mailbox]</address> - <ul> - ); + template = (const char *) { + Q(<li class="group">) + Q(<address class="[class]">[mailbox]</address>) + Q(<ul>) + }; } else { - template = TEMPLATE( - </ul> - </li> - ); + template = (const char *) { + Q(</ul>) + Q(</li>) + }; } struct Variable vars[] = { { "class", class }, @@ -55,9 +53,7 @@ static int htmlAddress(FILE *file, const char *class, struct Address addr) { static int htmlAddressList(FILE *file, const char *class, struct AddressList list) { if (!list.len) return 0; - const char *template = TEMPLATE( - <ul class="recipient [class]"> - ); + const char *template = Q(<ul class="recipient [class]">); struct Variable vars[] = { { "class", class }, {0}, @@ -68,7 +64,7 @@ htmlAddressList(FILE *file, const char *class, struct AddressList list) { error = htmlAddress(file, class, list.addrs[i]); if (error) return error; } - return templateRender(file, TEMPLATE(</ul>), NULL, NULL); + return templateRender(file, Q(</ul>), NULL, NULL); } static char *htmlReply(const struct Envelope *envelope) { @@ -111,9 +107,7 @@ static char *htmlMbox(const char *messageID) { static int htmlNavItem(FILE *file, const char *name, const char *base, const char *url) { - const char *template = TEMPLATE( - <li><a href="[base][url]">[name]</a></li> - ); + const char *template = Q(<li><a href="[base][url]">[name]</a></li>); struct Variable vars[] = { { "name", name }, { "base", base }, @@ -124,7 +118,7 @@ htmlNavItem(FILE *file, const char *name, const char *base, const char *url) { } int htmlMessageNav(FILE *file, const struct Envelope *envelope) { - int error = templateRender(file, TEMPLATE(<nav><ul>), NULL, NULL); + int error = templateRender(file, Q(<nav><ul>), NULL, NULL); if (error) return error; if (envelope->inReplyTo) { char *fragment = htmlFragment(envelope->inReplyTo); @@ -136,7 +130,7 @@ int htmlMessageNav(FILE *file, const struct Envelope *envelope) { error = htmlNavItem(file, "download", "", mbox); free(mbox); if (error) return error; - return templateRender(file, TEMPLATE(</ul></nav>), NULL, NULL); + return templateRender(file, Q(</ul></nav>), NULL, NULL); } static const char *htmlUTC(time_t time) { @@ -146,15 +140,15 @@ static const char *htmlUTC(time_t time) { } int htmlMessageOpen(FILE *file, const struct Envelope *envelope) { - const char *template = TEMPLATE( - <article class="message" id="[messageID]"> - <header> - <h2 class="subject"><a href="[fragment]">[subject]</a></h2> - <address class="from"> - <a href="[reply]">[from]</a> - </address> - <time datetime="[utc]">[date]</time> - ); + const char *template = { + Q(<article class="message" id="[messageID]">) + Q(<header>) + Q(<h2 class="subject"><a href="[fragment]">[subject]</a></h2>) + Q(<address class="from">) + Q(<a href="[reply]">[from]</a>) + Q(</address>) + Q(<time datetime="[utc]">[date]</time>) + }; char *fragment = htmlFragment(envelope->messageID); char *reply = htmlReply(envelope); struct Variable vars[] = { @@ -172,14 +166,14 @@ int htmlMessageOpen(FILE *file, const struct Envelope *envelope) { || htmlAddressList(file, "to", envelope->to) || htmlAddressList(file, "cc", envelope->cc) || htmlMessageNav(file, envelope) - || templateRender(file, TEMPLATE(</header>), NULL, NULL); + || templateRender(file, Q(</header>), NULL, NULL); free(reply); free(fragment); return error; } static int htmlInlineAttrs(FILE *file, const struct BodyPart *part) { - const char *template = " " TEMPLATE([attr]="[value]"); + const char *template = " " Q([attr]="[value]"); if (part->contentID) { struct Variable vars[] = { { "attr", "id" }, @@ -240,7 +234,7 @@ static int htmlMarkupURLs(FILE *file, char *buf) { if (error) return error; swap(&ptr[match[2].rm_so], &nul); - const char *template = TEMPLATE(<a href="[url]">[url]</a>); + const char *template = Q(<a href="[url]">[url]</a>); swap(&ptr[match[3].rm_so], &nul); struct Variable vars[] = { { "url", &ptr[match[2].rm_so] }, @@ -258,13 +252,13 @@ static int htmlMarkupQuote(FILE *file, char *buf) { size_t level = 0; for (char *ch = buf; *ch == '>' || *ch == ' '; level += (*ch++ == '>')); for (size_t i = 0; i < level; ++i) { - error = templateRender(file, TEMPLATE(<q>), NULL, NULL); + 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, TEMPLATE(</q>), NULL, NULL); + error = templateRender(file, Q(</q>), NULL, NULL); if (error) return error; } return 0; @@ -303,15 +297,15 @@ static int htmlMarkup(FILE *file, const char *content) { } if (patch && !regexec(®ex, buf, 0, NULL, 0)) { error = templateRender( - file, TEMPLATE(<b>[line]</b>), vars, escapeXML + file, Q(<b>[line]</b>), vars, escapeXML ); } else if (patch && buf[0] == '-' && strcmp(buf, "---")) { error = templateRender( - file, TEMPLATE(<del>[line]</del>), vars, escapeXML + file, Q(<del>[line]</del>), vars, escapeXML ); } else if (patch && buf[0] == '+') { error = templateRender( - file, TEMPLATE(<ins>[line]</ins>), vars, escapeXML + file, Q(<ins>[line]</ins>), vars, escapeXML ); } else if (patch) { error = escapeXML(file, buf); @@ -331,23 +325,23 @@ static int htmlMarkup(FILE *file, const char *content) { int htmlInline(FILE *file, const struct BodyPart *part, const char *content) { return 0 - || templateRender(file, TEMPLATE(<pre), NULL, NULL) + || templateRender(file, Q(<pre), NULL, NULL) || htmlInlineAttrs(file, part) - || templateRender(file, TEMPLATE(>), NULL, NULL) + || templateRender(file, Q(>), NULL, NULL) || htmlMarkup(file, content) - || templateRender(file, TEMPLATE(</pre>), NULL, NULL); + || templateRender(file, Q(</pre>), NULL, NULL); } int htmlAttachmentOpen(FILE *file) { - return templateRender(file, TEMPLATE(<ul class="attachment">), NULL, NULL); + return templateRender(file, Q(<ul class="attachment">), NULL, NULL); } int htmlAttachment( FILE *file, const struct BodyPart *part, const struct Variable *path ) { - const char *template = TEMPLATE( - <li><a href="[url]">[name][type][/][subtype]</a></li> - ); + const char *template = { + Q(<li><a href="[url]">[name][type][/][subtype]</a></li>) + }; char *url = templateURL("../" PATH_ATTACHMENT, path); const char *name = paramGet(part->disposition.params, "filename"); if (!name) name = paramGet(part->params, "name"); @@ -365,11 +359,11 @@ int htmlAttachment( } int htmlAttachmentClose(FILE *file) { - return templateRender(file, TEMPLATE(</ul>), NULL, NULL); + return templateRender(file, Q(</ul>), NULL, NULL); } int htmlMessageClose(FILE *file) { - return templateRender(file, TEMPLATE(</article>), NULL, NULL); + return templateRender(file, Q(</article>), NULL, NULL); } static char *htmlThreadURL(const struct Envelope *envelope, const char *type) { @@ -382,14 +376,14 @@ static char *htmlThreadURL(const struct Envelope *envelope, const char *type) { } int htmlThreadHead(FILE *file, const struct Envelope *envelope) { - const char *template = TEMPLATE( - <!DOCTYPE html> - <meta charset="utf-8"> - <meta name="generator" content="[generator]"> - <title>[subject] · [title]</title> - <link rel="alternate" type="application/atom+xml" href="[atom]"> - <link rel="alternate" type="application/mbox" href="[mbox]"> - ); + const char *template = { + Q(<!DOCTYPE html>) + Q(<meta charset="utf-8">) + Q(<meta name="generator" content="[generator]">) + Q(<title>[subject] · [title]</title>) + Q(<link rel="alternate" type="application/atom+xml" href="[atom]">) + Q(<link rel="alternate" type="application/mbox" href="[mbox]">) + }; char *atom = htmlThreadURL(envelope, "atom"); char *mbox = htmlThreadURL(envelope, "mbox"); struct Variable vars[] = { @@ -407,19 +401,19 @@ int htmlThreadHead(FILE *file, const struct Envelope *envelope) { } int htmlThreadOpen(FILE *file, const struct Envelope *envelope) { - const char *template = TEMPLATE( - <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> - </nav> - </header> - <main class="thread"> - ); + const char *template = { + Q(<header class="thread">) + Q(<h1>[subject]</h1>) + Q(<nav>) + Q(<ul>) + Q(<li><a href="../index.html">index</a></li>) + Q(<li><a href="[atom]">follow</a></li>) + Q(<li><a href="[mbox]">download</a></li>) + Q(</ul>) + Q(</nav>) + Q(</header>) + Q(<main class="thread">) + }; char *atom = htmlThreadURL(envelope, "atom"); char *mbox = htmlThreadURL(envelope, "mbox"); struct Variable vars[] = { @@ -448,16 +442,10 @@ static size_t threadCount(struct List thread) { int htmlSubthreadOpen(FILE *file, struct List thread) { const char *template = { - TEMPLATE( - <details class="subthread" open> - <summary> - ) - TEMPLATE ( - <data class="replies" value="[replies]">[replies] repl[ies]</data> - ) - TEMPLATE( - </summary> - ) + Q(<details class="subthread" open>) + Q(<summary>) + Q(<data class="replies" value="[replies]">[replies] repl[ies]</data>) + Q(</summary>) }; size_t count = threadCount(thread); char replies[32]; @@ -471,16 +459,19 @@ int htmlSubthreadOpen(FILE *file, struct List thread) { } int htmlSubthreadClose(FILE *file) { - return templateRender(file, TEMPLATE(</details>), NULL, NULL); + return templateRender(file, Q(</details>), NULL, NULL); } static int htmlFooter(FILE *file) { - const char *template = TEMPLATE( - <footer> - <small><a href="[generator]">generated</a> - <time datetime="[time]">[time]</time></small> - </footer> - ); + const char *template = { + Q(<footer>) + Q(<small>) + Q(<a href="[generator]">generated</a>) + " " + Q(<time datetime="[time]">[time]</time>) + Q(</small>) + Q(</footer>) + }; struct Variable vars[] = { { "generator", GENERATOR_URL }, { "time", htmlUTC(time(NULL)) }, @@ -491,18 +482,18 @@ static int htmlFooter(FILE *file) { int htmlThreadClose(FILE *file) { return 0 - || templateRender(file, TEMPLATE(</main>), NULL, NULL) + || templateRender(file, Q(</main>), NULL, NULL) || htmlFooter(file); } int htmlIndexHead(FILE *file) { - const char *template = TEMPLATE( - <!DOCTYPE html> - <meta charset="utf-8"> - <meta name="generator" content="[generator]"> - <title>[title]</title> - <link rel="alternate" type="application/atom+xml" href="index.atom"> - ); + const char *template = { + Q(<!DOCTYPE html>) + Q(<meta charset="utf-8">) + Q(<meta name="generator" content="[generator]">) + Q(<title>[title]</title>) + Q(<link rel="alternate" type="application/atom+xml" href="index.atom">) + }; struct Variable vars[] = { { "generator", GENERATOR_URL }, { "title", baseTitle }, @@ -513,7 +504,7 @@ int htmlIndexHead(FILE *file) { static int htmlIndexNav(FILE *file) { int error = 0 - || templateRender(file, TEMPLATE(<nav><ul>), NULL, NULL) + || templateRender(file, Q(<nav><ul>), NULL, NULL) || htmlNavItem(file, "follow", "", "index.atom"); if (error) return error; if (baseSubscribe) { @@ -522,23 +513,23 @@ static int htmlIndexNav(FILE *file) { } return 0 || htmlNavItem(file, "write", "mailto:", baseMailto) - || templateRender(file, TEMPLATE(</ul></nav>), NULL, NULL); + || templateRender(file, Q(</ul></nav>), NULL, NULL); } int htmlIndexOpen(FILE *file) { - const char *head = TEMPLATE( - <header class="index"> - <h1>[title]</h1> - ); + const char *head = { + Q(<header class="index">) + Q(<h1>[title]</h1>) + }; struct Variable vars[] = { { "title", baseTitle }, {0}, }; - const char *tail = TEMPLATE( - </header> - <main class="index"> - <ol> - ); + const char *tail = { + Q(</header>) + Q(<main class="index">) + Q(<ol>) + }; return 0 || templateRender(file, head, vars, escapeXML) || htmlIndexNav(file) @@ -557,14 +548,17 @@ static char *htmlIndexURL(const struct Envelope *envelope) { int htmlIndexThread( FILE *file, const struct Envelope *envelope, struct List thread ) { - const char *template = TEMPLATE( - <li> - <h2 class="subject"><a href="[url]">[subject]</a></h2> - <address class="from">[from]</address> - <time datetime="[utc]">[date]</time> - <data class="replies" value="[replies]">[replies] repl[ies]</data> - </li> - ); + const char *template = { + Q(<li>) + Q(<h2 class="subject"><a href="[url]">[subject]</a></h2>) + Q(<address class="from">[from]</address>) + Q(<time datetime="[utc]">[date]</time>) + " " + Q(<data class="replies" value="[replies]">) + Q([replies] repl[ies]) + Q(</data>) + Q(</li>) + }; char *url = htmlIndexURL(envelope); size_t count = threadCount(thread) - 1; char replies[32]; @@ -586,6 +580,6 @@ int htmlIndexThread( int htmlIndexClose(FILE *file) { return 0 - || templateRender(file, TEMPLATE(</ol></main>), NULL, NULL) + || templateRender(file, Q(</ol></main>), NULL, NULL) || htmlFooter(file); } |