ssnail

crappy and opinionated static site generator
git clone https://git.e1e0.net/ssnail.git
Log | Files | Refs | README | LICENSE

commit 35e6666986e5793bd0a5b4b7abbed2bfa1224080
parent 7e2cec0aa0face7fe3b55c9f784da0332e2d289e
Author: Paco Esteban <paco@e1e0.net>
Date:   Sun, 24 May 2020 20:50:19 +0200

basic html index (optional).

date order is still pending.

Diffstat:
Mssnail.c | 93++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 76 insertions(+), 17 deletions(-)

diff --git a/ssnail.c b/ssnail.c @@ -24,6 +24,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <time.h> #include <unistd.h> #include <lowdown.h> @@ -40,6 +41,7 @@ struct article { char *title; char *author; char *date; + char *type; long long src_mtime; long long dst_mtime; SLIST_ENTRY(article) entries; @@ -49,27 +51,28 @@ struct article *a = NULL; SLIST_HEAD(listhead, article) head; char *str_rep(const char *, const char *, const char *); -int gen_html(char **, size_t *, char **, char **, char **, char *, size_t); +int gen_html(struct article *); int build_full_path(char *, char *, char *); int load_from_file(char **, char *); void usage(); int populate_article_entry(struct article *); int write_html(struct article *, char *, char *); void articleq_free(struct listhead *); +int generate_index(struct listhead *, char *, char *, char *); int main(int argc, char *argv[]) { DIR *dirp; struct dirent *dp; - int ch, force = 0; + int ch, force = 0, index = 0, needs_index = 0; char srcdir[PATH_MAX] = "", dstdir[PATH_MAX] = "", header_tpl[PATH_MAX] = "./_header.html", footer_tpl[PATH_MAX] = "./_footer.html", *fbuf = NULL; struct article *ap = NULL; - while ((ch = getopt(argc, argv, "F:H:d:fs:")) != -1) { + while ((ch = getopt(argc, argv, "F:H:d:fis:")) != -1) { switch (ch) { case 'F': (void)strlcpy(footer_tpl, optarg, PATH_MAX); @@ -83,6 +86,9 @@ main(int argc, char *argv[]) case 'f': force = 1; break; + case 'i': + index = 1; + break; case 's': (void)strlcpy(srcdir, optarg, PATH_MAX); break; @@ -117,20 +123,72 @@ main(int argc, char *argv[]) closedir(dirp); free(fbuf); - printf("Generating html files ... \n"); + printf("Generate html files ... \n"); SLIST_FOREACH(ap, &head, entries) { if ((ap->src_mtime > ap->dst_mtime) || force) { printf("... %s\n", ap->dst_path); if (write_html(ap, header_tpl, footer_tpl) == -1) err(3, "cannot write html file"); + needs_index = 1; } } + if (index && (needs_index || force)) { + printf("Generate html index ... \n"); + generate_index(&head, header_tpl, footer_tpl, dstdir); + } + articleq_free(&head); return 0; } +int +generate_index(struct listhead *h, char head_tpl[PATH_MAX], + char foot_tpl[PATH_MAX], char *dst_dir) +{ + struct article *a; + char *header = NULL, *footer = NULL; + FILE *fout; + int r = -1; + time_t now; + struct tm *timeInfo; + char mytime[12], index_path[PATH_MAX]; + + time(&now); + timeInfo = localtime(&now); + strftime(mytime, sizeof(mytime), "%Y-%m-%d", timeInfo); + + load_from_file(&header, head_tpl); + header = str_rep(header, "$title$", "index"); + header = str_rep(header, "$author$", getlogin()); + header = str_rep(header, "$date$", mytime); + load_from_file(&footer, foot_tpl); + footer = str_rep(footer, "$title$", "index"); + + build_full_path(index_path, dst_dir, "index.html"); + if ((fout = fopen(index_path, "w")) == NULL) + goto out; + fwrite(header, 1, strlen(header), fout); + // TODO: make this list reverse date ordered + fprintf(fout, "<ul>\n"); + SLIST_FOREACH(a, h, entries) { + if (strcmp(a->type, "article") == 0) + fprintf(fout, "<li><a href='%s'>%s</a></li>\n", + a->dst_path, a->title); + } + fprintf(fout, "</ul>\n"); + fwrite(footer, 1, strlen(footer), fout); + fclose(fout); + + r = 0; +out: + free(header); + free(footer); + return r; + +} + void articleq_free(struct listhead *h) { @@ -199,9 +257,7 @@ str_rep(const char *s, const char *oldW, const char *newW) } int -gen_html(char **dest, size_t *destz, - char **title, char **author, char **date, - char *orig, size_t origz) +gen_html(struct article *a) { struct lowdown_opts opts; struct lowdown_metaq mq; @@ -230,22 +286,27 @@ gen_html(char **dest, size_t *destz, // use strlen(orig) here because the of the \0 char that // was showing up on the dest buffer. // playing with origz did not work here. - lowdown_buf(&opts, orig, strlen(orig), dest, destz, &mq); + lowdown_buf(&opts, a->orig_content, strlen(a->orig_content), + &a->html_content, &a->htmlz, &mq); TAILQ_FOREACH(md, &mq, entries) { size_t valz = (strlen(md->value) > MAX_META) ? MAX_META : strlen(md->value) + 1; if (strcmp(md->key, "title") == 0 ) { - *title = malloc(valz); - (void)strlcpy(*title, md->value, valz); + a->title = malloc(valz); + (void)strlcpy(a->title, md->value, valz); } if (strcmp(md->key, "author") == 0 ) { - *author = malloc(valz); - (void)strlcpy(*author, md->value, valz); + a->author = malloc(valz); + (void)strlcpy(a->author, md->value, valz); } if (strcmp(md->key, "date") == 0 ) { - *date = malloc(valz); - (void)strlcpy(*date, md->value, valz); + a->date = malloc(valz); + (void)strlcpy(a->date, md->value, valz); + } + if (strcmp(md->key, "type") == 0 ) { + a->type = malloc(valz); + (void)strlcpy(a->type, md->value, valz); } } @@ -312,9 +373,7 @@ populate_article_entry(struct article *ap) if ((ap->origz = load_from_file(&ap->orig_content, ap->src_path)) == 0) goto out; - gen_html(&ap->html_content, &ap->htmlz, - &ap->title, &ap->author, &ap->date, - ap->orig_content, ap->origz); + gen_html(ap); retval = 0; out: return retval;