diff options
author | June McEnroe <june@causal.agency> | 2020-04-23 11:37:51 -0400 |
---|---|---|
committer | June McEnroe <june@causal.agency> | 2020-04-23 11:37:51 -0400 |
commit | a204deb1bc65a2d52f23bade4cdc4b319a62edf3 (patch) | |
tree | 29f6320861c95d619ac926648c2e0eb976109930 | |
parent | Make sure to close attachment <ul> at end of multipart (diff) | |
download | bubger-a204deb1bc65a2d52f23bade4cdc4b319a62edf3.tar.gz bubger-a204deb1bc65a2d52f23bade4cdc4b319a62edf3.zip |
Add basic patch highlighting
-rw-r--r-- | html.c | 66 |
1 files changed, 60 insertions, 6 deletions
diff --git a/html.c b/html.c index 5f7dc16..b883414 100644 --- a/html.c +++ b/html.c @@ -167,7 +167,7 @@ int htmlMessageOpen(FILE *file, const struct Envelope *envelope) { return error; } -int htmlInlineAttrs(FILE *file, const struct BodyPart *part) { +static int htmlInlineAttrs(FILE *file, const struct BodyPart *part) { const char *template = " [attr]=\"[value]\""; if (part->id) { struct Variable vars[] = { @@ -204,14 +204,68 @@ int htmlInlineAttrs(FILE *file, const struct BodyPart *part) { return 0; } +static bool isPatch(const char *content) { + return !strncmp(content, "---\n", 4) || strstr(content, "\n---\n"); +} + +static int htmlPatch(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; + if (cap < len + 1) { + cap = len + 1; + buf = realloc(buf, cap); + if (!buf) err(EX_OSERR, "realloc"); + } + memcpy(buf, content, len); + buf[len] = '\0'; + struct Variable vars[] = { + { "line", buf }, + {0}, + }; + + if (!strcmp(buf, "---\n")) { + patch = true; + } else if (patch && !strcmp(buf, "-- \n")) { + patch = false; + } + + if (patch && !strncmp(buf, "@@", 2)) { + error = templateRender( + file, TEMPLATE(<b>[line]</b>), vars, escapeXML + ); + } else if (patch && buf[0] == '-' && strncmp(buf, "---", 3)) { + error = templateRender( + file, TEMPLATE(<del>[line]</del>), vars, escapeXML + ); + } else if (patch && buf[0] == '+' && strncmp(buf, "+++", 3)) { + error = templateRender( + file, TEMPLATE(<ins>[line]</ins>), vars, escapeXML + ); + } else { + error = escapeXML(file, buf); + } + if (error) break; + } + free(buf); + return error; +} + int htmlInline(FILE *file, const struct BodyPart *part, const char *content) { - // TODO: Process diffs -> <ins>, <del> - return 0 + int error = 0 || templateRender(file, TEMPLATE(<pre), NULL, NULL) || htmlInlineAttrs(file, part) - || templateRender(file, TEMPLATE(>), NULL, NULL) - || escapeXML(file, content) - || templateRender(file, TEMPLATE(</pre>), NULL, NULL); + || templateRender(file, TEMPLATE(>), NULL, NULL); + if (error) return error; + if (isPatch(content)) { + error = htmlPatch(file, content); + } else { + error = escapeXML(file, content); + } + return error || templateRender(file, TEMPLATE(</pre>), NULL, NULL); } int htmlAttachmentOpen(FILE *file) { |