summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--html.c62
1 files changed, 32 insertions, 30 deletions
diff --git a/html.c b/html.c
index bdbc59c..5147798 100644
--- a/html.c
+++ b/html.c
@@ -137,8 +137,13 @@ int htmlMessageNav(FILE *file, const struct Envelope *envelope) {
 	return templateRender(file, TEMPLATE(</ul></nav>), NULL, NULL);
 }
 
+static const char *htmlUTC(time_t time) {
+	static char buf[sizeof("0000-00-00T00:00:00Z")];
+	strftime(buf, sizeof(buf), "%FT%TZ", gmtime(&time));
+	return buf;
+}
+
 int htmlMessageOpen(FILE *file, const struct Envelope *envelope) {
-	// TODO: Conditionally include mailto: link.
 	const char *template = TEMPLATE(
 		<article class="message" id="[messageID]">
 		<header>
@@ -150,15 +155,13 @@ int htmlMessageOpen(FILE *file, const struct Envelope *envelope) {
 	);
 	char *fragment = htmlFragment(envelope->messageID);
 	char *reply = htmlReply(envelope);
-	char utc[sizeof("0000-00-00T00:00:00Z")];
-	strftime(utc, sizeof(utc), "%FT%TZ", gmtime(&envelope->time));
 	struct Variable vars[] = {
 		{ "messageID", envelope->messageID },
 		{ "fragment", fragment },
 		{ "subject", envelope->subject },
 		{ "reply", reply },
 		{ "from", addressName(envelope->from) },
-		{ "utc", utc },
+		{ "utc", htmlUTC(envelope->time) },
 		{ "date", envelope->date },
 		{0},
 	};
@@ -174,7 +177,7 @@ int htmlMessageOpen(FILE *file, const struct Envelope *envelope) {
 }
 
 static int htmlInlineAttrs(FILE *file, const struct BodyPart *part) {
-	const char *template = " [attr]=\"[value]\"";
+	const char *template = " " TEMPLATE([attr]="[value]");
 	if (part->contentID) {
 		struct Variable vars[] = {
 			{ "attr", "id" },
@@ -210,13 +213,13 @@ static int htmlInlineAttrs(FILE *file, const struct BodyPart *part) {
 	return 0;
 }
 
-static int htmlHighlight(FILE *file, const char *content) {
+static int htmlMarkup(FILE *file, const char *content) {
 	int error = 0;
 	size_t cap = 0;
 	char *buf = NULL;
 	bool patch = false;
 	for (const char *nl; (nl = strchr(content, '\n')); content = &nl[1]) {
-		size_t len = &nl[1] - content;
+		size_t len = nl - content;
 		if (cap < len + 1) {
 			cap = len + 1;
 			buf = realloc(buf, cap);
@@ -229,30 +232,30 @@ static int htmlHighlight(FILE *file, const char *content) {
 			{0},
 		};
 
-		if (!strcmp(buf, "---\n")) {
+		if (!strcmp(buf, "---")) {
 			patch = true;
-		} else if (patch && !strcmp(buf, "-- \n")) {
+		} else if (patch && !strcmp(buf, "-- ")) {
 			patch = false;
 		}
 
 		if (patch && !strncmp(buf, "@@", 2)) {
 			error = templateRender(
-				file, TEMPLATE(<b>[line]</b>), vars, escapeXML
+				file, TEMPLATE(<b>[line]</b>) "\n", vars, escapeXML
 			);
 		} else if (patch && buf[0] == '-' && strncmp(buf, "---", 3)) {
 			error = templateRender(
-				file, TEMPLATE(<del>[line]</del>), vars, escapeXML
+				file, TEMPLATE(<del>[line]</del>) "\n", vars, escapeXML
 			);
 		} else if (patch && buf[0] == '+' && strncmp(buf, "+++", 3)) {
 			error = templateRender(
-				file, TEMPLATE(<ins>[line]</ins>), vars, escapeXML
+				file, TEMPLATE(<ins>[line]</ins>) "\n", vars, escapeXML
 			);
 		} else if (buf[0] == '>') {
 			error = templateRender(
-				file, TEMPLATE(<q>[line]</q>), vars, escapeXML
+				file, TEMPLATE(<q>[line]</q>) "\n", vars, escapeXML
 			);
 		} else {
-			error = escapeXML(file, buf);
+			error = templateRender(file, "[line]\n", vars, escapeXML);
 		}
 		if (error) break;
 	}
@@ -265,7 +268,7 @@ int htmlInline(FILE *file, const struct BodyPart *part, const char *content) {
 		|| templateRender(file, TEMPLATE(<pre), NULL, NULL)
 		|| htmlInlineAttrs(file, part)
 		|| templateRender(file, TEMPLATE(>), NULL, NULL)
-		|| htmlHighlight(file, content)
+		|| htmlMarkup(file, content)
 		|| templateRender(file, TEMPLATE(</pre>), NULL, NULL);
 }
 
@@ -376,14 +379,18 @@ 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>
-	);
+	const char *template = {
+		TEMPLATE(
+			<details class="subthread" open>
+			<summary>
+		)
+		TEMPLATE (
+			<data class="replies" value="[replies]">[replies] repl[ies]</data>
+		)
+		TEMPLATE(
+			</summary>
+		)
+	};
 	size_t count = threadCount(thread);
 	char replies[32];
 	snprintf(replies, sizeof(replies), "%zu", count);
@@ -403,11 +410,8 @@ static int htmlFooter(FILE *file) {
 	const char *template = TEMPLATE(
 		<footer>generated <time datetime="[time]">[time]</time></footer>
 	);
-	time_t now = time(NULL);
-	char time[sizeof("0000-00-00T00:00:00Z")];
-	strftime(time, sizeof(time), "%FT%TZ", gmtime(&now));
 	struct Variable vars[] = {
-		{ "time", time },
+		{ "time", htmlUTC(time(NULL)) },
 		{0},
 	};
 	return templateRender(file, template, vars, escapeXML);
@@ -476,8 +480,6 @@ int htmlIndexThread(
 		</li>
 	);
 	char *url = htmlIndexURL(envelope);
-	char utc[sizeof("0000-00-00T00:00:00Z")];
-	strftime(utc, sizeof(utc), "%FT%TZ", gmtime(&envelope->time));
 	size_t count = threadCount(thread) - 1;
 	char replies[32];
 	snprintf(replies, sizeof(replies), "%zu", count);
@@ -485,7 +487,7 @@ int htmlIndexThread(
 		{ "url", url },
 		{ "subject", envelope->subject },
 		{ "from", addressName(envelope->from) },
-		{ "utc", utc },
+		{ "utc", htmlUTC(envelope->time) },
 		{ "date", envelope->date },
 		{ "replies", replies },
 		{ "ies", (count == 1 ? "y" : "ies") },