saait

Simple static page generator
git clone https://git.sinitax.com/codemadness/saait
Log | Files | Refs | README | LICENSE | Upstream | sfeed.txt

commit 627a6cda2e82c3f4937d7fb0cc82f54549bd15ac
parent 019974557f4301fbfff9b4846490c20f623653a5
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date:   Sun, 27 Nov 2016 12:53:55 +0100

wip

Diffstat:
MREADME | 8++++----
MTODO | 13+++++++++++++
Mconfig.h | 46+++++++++++++++++++++++++---------------------
Mpages/001-gothic-1-guide.cfg | 1+
Mpages/002-getting-the-usb-powerline-bridge-to-work-on-linux.cfg | 1+
Mpages/003-driconf-enabling-s3-texture-compression-on-linux.cfg | 1+
Mpages/004-query-unused-css-rules-on-current-document-state.cfg | 1+
Mpages/005-dwm-hiltjo-my-windowmanager-configuration.cfg | 1+
Mpages/006-gtk2-theme-gtk-murrine-rape.cfg | 1+
Mpages/007-seturgent-set-urgency-hints-for-x-applications.cfg | 1+
Mpages/009-vim-theme-relaxed.cfg | 1+
Mpages/010-sfeed-simple-feed-parser.cfg | 1+
Mpages/011-userscript-block-stupid-fonts.cfg | 1+
Mpages/012-userscript-youtube-circumvent-age-verification.cfg | 1+
Mpages/013-userscript-focus-input-field.cfg | 1+
Mpages/015-mg-openbsd-port.cfg | 1+
Mpages/016-twitch-interface.cfg | 1+
Mpages/017-openbsd-httpd-and-cgit.cfg | 1+
Msaait.c | 89+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Mtemplates/page/item.html | 2+-
20 files changed, 106 insertions(+), 67 deletions(-)

diff --git a/README b/README @@ -8,7 +8,7 @@ Some parts are intentionally hardcoded, C knowledge is required. Dependencies: ------------- -- C compiler +- C compiler (C99) - libc - requires non-standard field tm_gmtoff in struct tm. @@ -16,7 +16,7 @@ Dependencies: Tested and works on: -------------------- - OpenBSD -- Windows (mingw) +- Windows (mingw and cygwin) Directory structure for pages: @@ -45,8 +45,8 @@ Cfg file and template syntax: ----------------------------- Variables set: -file (if not already set) path to HTML content filename. -filename basename of content HTML file. +htmlfile (if not already set) path to input HTML content filename. +filename (can be overwritten) basename of output content HTML file. Variables: diff --git a/TODO b/TODO @@ -1,3 +1,16 @@ +optimize readfile: don't copy data twice (memcpy). + +reduce memory usage. + +allow to override output filename (for no prefix number). + +writepage() improve error messages for filenames (error on line ...). + show template name and filename. + +cfgfile: spaces around = skip + +don't use strndup or wrap it. + simplify date parsing. improve documentation diff --git a/config.h b/config.h @@ -4,49 +4,53 @@ static const char *templatedir = "templates"; enum { BlockHeader = 0, BlockItem, BlockFooter, BlockLast }; -static struct { +struct block { + char *name; /* filename */ + char *data; /* content (set at runtime) */ +}; + +struct template { char *name; /* blocks: header, item, footer */ - struct { - char *name; /* filename */ - char *data; /* content (set at runtime) */ - } blocks[BlockLast]; + struct block blocks[BlockLast]; /* output FILE * (set at runtime) */ FILE *fp; -} templates[] = { +}; + +static struct template templates[] = { { .name = "atom.xml", .blocks = { - { .name = "header.xml" }, - { .name = "item.xml" }, - { .name = "footer.xml" } + { .name = "atom.xml/header.xml" }, + { .name = "atom.xml/item.xml" }, + { .name = "atom.xml/footer.xml" } } }, { .name = "index.html", .blocks = { - { .name = "header.html" }, - { .name = "item.html" }, - { .name = "footer.html" } + { .name = "index.html/header.html" }, + { .name = "index.html/item.html" }, + { .name = "index.html/footer.html" } } }, { .name = "page", .blocks = { - { .name = "header.html" }, - { .name = "item.html" }, - { .name = "footer.html" } + { .name = "page/header.html" }, + { .name = "page/item.html" }, + { .name = "page/footer.html" } } }, { .name = "sitemap.xml", .blocks = { - { .name = "header.xml" }, - { .name = "item.xml" }, - { .name = "footer.xml" } + { .name = "sitemap.xml/header.xml" }, + { .name = "sitemap.xml/item.xml" }, + { .name = "sitemap.xml/footer.xml" } } }, { .name = "urllist.txt", .blocks = { - { .name = "header.txt" }, - { .name = "item.txt" }, - { .name = "footer.txt" } + { .name = "urllist.txt/header.txt" }, + { .name = "urllist.txt/item.txt" }, + { .name = "urllist.txt/footer.txt" } } } }; diff --git a/pages/001-gothic-1-guide.cfg b/pages/001-gothic-1-guide.cfg @@ -1,3 +1,4 @@ +filename=gothic-1-guide.html title=Gothic 1 game guide description=Gothic 1 game guide with some useful tips id=gothic-1-guide diff --git a/pages/002-getting-the-usb-powerline-bridge-to-work-on-linux.cfg b/pages/002-getting-the-usb-powerline-bridge-to-work-on-linux.cfg @@ -1,3 +1,4 @@ +filename=getting-the-usb-powerline-bridge-to-work-on-linux.html title=Getting the USB-powerline bridge to work on Linux description=A guide to get a USB-powerline bridge with the Intellon 51x1 chipset working on Linux id=getting-the-usb-powerline-bridge-to-work-on-linux diff --git a/pages/003-driconf-enabling-s3-texture-compression-on-linux.cfg b/pages/003-driconf-enabling-s3-texture-compression-on-linux.cfg @@ -1,3 +1,4 @@ +filename=driconf-enabling-s3-texture-compression-on-linux.html title=Driconf: enabling S3 texture compression on Linux description=driconf: enabling S3 texture compression tags=HOWTO, linux, s3tc, driconf diff --git a/pages/004-query-unused-css-rules-on-current-document-state.cfg b/pages/004-query-unused-css-rules-on-current-document-state.cfg @@ -1,3 +1,4 @@ +filename=query-unused-css-rules-on-current-document-state.html title=Query unused CSS rules on current document state description=How to see all the rules in a stylesheet (CSS) that are not used for the current document id=query-unused-css-rules-on-current-document-state diff --git a/pages/005-dwm-hiltjo-my-windowmanager-configuration.cfg b/pages/005-dwm-hiltjo-my-windowmanager-configuration.cfg @@ -1,3 +1,4 @@ +filename=dwm-hiltjo-my-windowmanager-configuration.html title=DWM-hiltjo: my windowmanager configuration description=My DWM configuration; a few added features to suit my needs tags=dwm, suckless diff --git a/pages/006-gtk2-theme-gtk-murrine-rape.cfg b/pages/006-gtk2-theme-gtk-murrine-rape.cfg @@ -1,3 +1,4 @@ +filename=gtk2-theme-gtk-murrine-rape.html title=GTK2 theme: gtk-murrine-rape description=A plain consistent GTK2 theme with no fluff (rounded borders, animations, etc) id=gtk2-theme-gtk-murrine-rape diff --git a/pages/007-seturgent-set-urgency-hints-for-x-applications.cfg b/pages/007-seturgent-set-urgency-hints-for-x-applications.cfg @@ -1,3 +1,4 @@ +filename=seturgent-set-urgency-hints-for-x-applications.html title=Seturgent: set urgency hints for X applications description=Seturgent is a small utility to set an application it's urgency hint id=seturgent-set-urgency-hints-for-x-applications diff --git a/pages/009-vim-theme-relaxed.cfg b/pages/009-vim-theme-relaxed.cfg @@ -1,3 +1,4 @@ +filename=vim-theme-relaxed.html title=Vim theme: relaxed description=a dark VIM theme I made and use on a daily basis tags=theme, vim diff --git a/pages/010-sfeed-simple-feed-parser.cfg b/pages/010-sfeed-simple-feed-parser.cfg @@ -1,3 +1,4 @@ +filename=sfeed-simple-feed-parser.html title=Sfeed: simple RSS and Atom parser description=a simple RSS and Atom parser (and scripts to add reader functionality) id=sfeed-simple-feed-parser diff --git a/pages/011-userscript-block-stupid-fonts.cfg b/pages/011-userscript-block-stupid-fonts.cfg @@ -1,3 +1,4 @@ +filename=userscript-block-stupid-fonts.html title=Userscript: block stupid fonts description=Userscript to whitelist your favorite fonts and block the rest tags=userscript, greasemonkey, block fonts diff --git a/pages/012-userscript-youtube-circumvent-age-verification.cfg b/pages/012-userscript-youtube-circumvent-age-verification.cfg @@ -1,3 +1,4 @@ +filename=userscript-youtube-circumvent-age-verification.html title=Userscript: Youtube circumvent age verification description=Userscript to circumvent Youtube age verification and redirect to the video tags=userscript, greasemonkey, youtube, skip, circumvent, age verification diff --git a/pages/013-userscript-focus-input-field.cfg b/pages/013-userscript-focus-input-field.cfg @@ -1,3 +1,4 @@ +filename=userscript-focus-input-field.html title=Userscript: focus input field description=Userscript to focus the first input field on a page with a hotkey tags=userscript, focus, input, greasemonkey diff --git a/pages/015-mg-openbsd-port.cfg b/pages/015-mg-openbsd-port.cfg @@ -1,3 +1,4 @@ +filename=mg-openbsd-port.html title=mg: port of OpenBSD mg version to Linux description=mg: port of OpenBSD mg version to Linux tags=mg, openbsd, port diff --git a/pages/016-twitch-interface.cfg b/pages/016-twitch-interface.cfg @@ -1,3 +1,4 @@ +filename=twitch-interface.html title=twitch-go: web application to watch Twitch streams description=twitch-go: web application to watch Twitch streams tags=twitch, api, Golang diff --git a/pages/017-openbsd-httpd-and-cgit.cfg b/pages/017-openbsd-httpd-and-cgit.cfg @@ -1,3 +1,4 @@ +filename=openbsd-httpd-and-cgit.html title=OpenBSD httpd, slowcgi and cgit description=OpenBSD httpd, slowcgi and cgit tags=OpenBSD httpd, slowcgi, cgit, FastCGI diff --git a/saait.c b/saait.c @@ -10,11 +10,6 @@ #define STRP(s) s,sizeof(s)-1 #define LEN(s) (sizeof(s)/sizeof(*s)) -#include "arg.h" -char *argv0; - -#include "config.h" - struct config { struct variable *vars; }; @@ -26,6 +21,11 @@ struct variable { struct variable *next; }; +#include "arg.h" +char *argv0; + +#include "config.h" + static struct config *global; /* Escape characters below as HTML 2.0 / XML 1.0. */ @@ -256,9 +256,12 @@ struct config * readconfig(const char *file) { struct config *c; + char *data; c = ecalloc(1, sizeof(*c)); - c->vars = parsevars(readfile(file)); + data = readfile(file); + c->vars = parsevars(data); + free(data); return c; } @@ -351,8 +354,11 @@ int main(int argc, char *argv[]) { struct config *c; - char *p, *base, *basefile, file[PATH_MAX], outputfile[PATH_MAX]; - int i, j, r; + struct block *b; + struct variable *v; + char *base, *filename, *p; + char file[PATH_MAX], htmlfile[PATH_MAX], outputfile[PATH_MAX]; + int i, j, k, r; #ifdef __OpenBSD__ if (pledge("stdio cpath rpath wpath", NULL) == -1) { @@ -381,12 +387,13 @@ main(int argc, char *argv[]) /* load templates: all templates must be loaded correctly first. */ for (i = 0; i < LEN(templates); i++) { for (j = 0; j < LEN(templates[i].blocks); j++) { - r = snprintf(file, sizeof(file), "%s/%s/%s", templatedir, templates[i].name, templates[i].blocks[j].name); + b = &templates[i].blocks[j]; + r = snprintf(file, sizeof(file), "%s/%s", templatedir, b->name); if (r < 0 || (size_t) r >= sizeof(file)) { - fprintf(stderr, "path truncated: '%s/%s/%s'\n", templatedir, templates[i].name, templates[i].blocks[j].name); + fprintf(stderr, "path truncated: '%s/%s'\n", templatedir, b->name); exit(1); } - templates[i].blocks[j].data = readfile(file); + b->data = readfile(file); } } @@ -399,8 +406,9 @@ main(int argc, char *argv[]) fprintf(stderr, "path truncated: '%s/%s'\n", outputdir, templates[i].name); exit(1); } - if ((templates[i].fp = efopen(file, "wb"))) - writepage(templates[i].fp, "", NULL, templates[i].blocks[BlockHeader].data); + templates[i].fp = efopen(file, "wb"); + b = &templates[i].blocks[BlockHeader]; + writepage(templates[i].fp, b->name, NULL, b->data); } /* pages */ @@ -414,49 +422,47 @@ main(int argc, char *argv[]) c = readconfig(argv[i]); /* read file data */ - r = snprintf(file, sizeof(file), "%s.html", base); - if (r < 0 || (size_t)r >= sizeof(file)) { + r = snprintf(htmlfile, sizeof(htmlfile), "%s.html", base); + if (r < 0 || (size_t)r >= sizeof(htmlfile)) { fprintf(stderr, "path truncated: '%s.html'\n", base); exit(1); } - - /* set file if not set */ - if (!getvar(c->vars, "file")) - setvar(&c->vars, newvar("file", file)); - - /* set HTML filename */ - if ((p = strrchr(file, '/'))) - setvar(&c->vars, newvar("filename", &file[p - file + 1])); - else - setvar(&c->vars, newvar("filename", file)); + /* set htmlfile if not set */ + if (!getvar(c->vars, "htmlfile")) + setvar(&c->vars, newvar("htmlfile", htmlfile)); + + /* set HTML output filename (with part removed), allow to override it. */ + if (!getvar(c->vars, "filename")) { + if ((p = strrchr(htmlfile, '/'))) + setvar(&c->vars, newvar("filename", &htmlfile[p - htmlfile + 1])); + else + setvar(&c->vars, newvar("filename", htmlfile)); + } + /* get output filename */ + v = getvar(c->vars, "filename"); + filename = v->value; /* item block */ for (j = 0; j < LEN(templates); j++) { /* TODO: page is a special case for now */ if (!strcmp(templates[j].name, "page")) { - if ((p = strrchr(base, '/'))) - basefile = estrdup(&base[p - base + 1]); - else - basefile = estrdup(base); - /* output file */ - r = snprintf(outputfile, sizeof(outputfile), "%s/%s.html", outputdir, basefile); - if (r < 0 || (size_t)r >= sizeof(file)) { - fprintf(stderr, "path truncated: '%s/%s.html'\n", outputdir, basefile); + r = snprintf(outputfile, sizeof(outputfile), "%s/%s", outputdir, filename); + if (r < 0 || (size_t)r >= sizeof(outputfile)) { + fprintf(stderr, "path truncated: '%s/%s'\n", outputdir, filename); exit(1); } templates[j].fp = efopen(outputfile, "wb"); - writepage(templates[j].fp, file, c, templates[j].blocks[BlockHeader].data); - writepage(templates[j].fp, file, c, templates[j].blocks[BlockItem].data); - writepage(templates[j].fp, file, c, templates[j].blocks[BlockFooter].data); - + for (k = 0; k < LEN(templates[j].blocks); k++) { + b = &templates[j].blocks[k]; + writepage(templates[j].fp, b->name, c, b->data); + } fclose(templates[j].fp); templates[j].fp = NULL; - - free(basefile); } else { - writepage(templates[j].fp, file, c, templates[j].blocks[BlockItem].data); + b = &templates[j].blocks[BlockItem]; + writepage(templates[j].fp, b->name, c, b->data); } } free(base); @@ -467,7 +473,8 @@ main(int argc, char *argv[]) for (i = 0; i < LEN(templates); i++) { if (!strcmp(templates[i].name, "page")) continue; - writepage(templates[i].fp, "", NULL, templates[i].blocks[BlockFooter].data); + b = &templates[i].blocks[BlockFooter]; + writepage(templates[i].fp, b->name, NULL, b->data); } return 0; diff --git a/templates/page/item.html b/templates/page/item.html @@ -1,3 +1,3 @@ <h1><a href="">${title}</a></h1> <em><strong>Written:</strong> ${created}</em> - %{file} + %{htmlfile}