commit bb296fc81fc4ca42e7b739acafc3018077b750ee
parent 4ed7276d30b480f7015e0857142745b52a7ed0d0
Author: Jacob R. Edwards <jacob@jacobedwards.org>
Date: Tue, 12 Mar 2024 16:36:43 -0700
Implement a better HTML document initializer
This function takes a struct which gives the document title aswell
as any CSS or scripts to include and handles setting the title and
including the resources while writing the boilerplate HTML.
It replaces htmlstartdoc(), but also adds a function to end the
document.
Diffstat:
8 files changed, 110 insertions(+), 35 deletions(-)
diff --git a/page.c b/page.c
@@ -40,6 +40,62 @@ freepagerequest(struct pagedata *pd)
}
enum kcgi_err
+startpage(struct pagedata *pd, struct pagetemplate *t, enum khttp code)
+{
+ char **p;
+ enum kcgi_err status;
+
+ if ((status = khttp_head(&pd->req, kresps[KRESP_STATUS],
+ "%s", khttps[code])) != KCGI_OK ||
+ (status = khttp_head(&pd->req, kresps[KRESP_CONTENT_TYPE],
+ "%s", kmimetypes[KMIME_TEXT_HTML])) != KCGI_OK ||
+ (status = khttp_body(&pd->req)) != KCGI_OK)
+ return status;
+
+ if ((status = khtml_open(&pd->html, &pd->req, KHTML_PRETTY)) != KCGI_OK ||
+ (status = khtml_elem(&pd->html, KELEM_DOCTYPE)) != KCGI_OK ||
+ (status = khtml_elem(&pd->html, KELEM_HTML)) != KCGI_OK ||
+ (status = khtml_elem(&pd->html, KELEM_HEAD)) != KCGI_OK ||
+ (status = khtml_elem(&pd->html, KELEM_TITLE)) != KCGI_OK ||
+ (status = khtml_puts(&pd->html, t->title ? t->title : "Untitled")) != KCGI_OK ||
+ (status = khtml_closeelem(&pd->html, 1)) != KCGI_OK)
+ return status;
+
+ if (t->css) {
+ for (p = t->css; *p; ++p) {
+ if ((status = khtml_attr(&pd->html, KELEM_LINK,
+ KATTR_HREF, *p, KATTR_REL, "stylesheet", KATTR__MAX)) != KCGI_OK ||
+ (status = khtml_closeelem(&pd->html, 1)) != KCGI_OK)
+ return status;
+ }
+ }
+
+ if ((status = khtml_elem(&pd->html, KELEM_BODY)) != KCGI_OK)
+ return status;
+ pd->bodypos = khtml_elemat(&pd->html);
+ return KCGI_OK;
+}
+
+enum kcgi_err
+endpage(struct pagedata *pd, struct pagetemplate *t)
+{
+ char **p;
+ enum kcgi_err status;
+
+ khtml_closeto(&pd->html, pd->bodypos);
+ if (t->scripts) {
+ for (p = t->scripts; *p; ++p) {
+ if ((status = khtml_attr(&pd->html, KELEM_SCRIPT,
+ KATTR_SRC, *p, KATTR__MAX)) != KCGI_OK ||
+ (status = khtml_closeelem(&pd->html, 1)) != KCGI_OK)
+ return status;
+ }
+ }
+
+ return khtml_closeelem(&pd->html, -1);
+}
+
+enum kcgi_err
errorpage(struct pagedata *pd, enum khttp code)
{
enum kcgi_err status;
diff --git a/page.h b/page.h
@@ -8,10 +8,19 @@ struct pagedata {
struct kvalid *keys;
char **pages; /* page names */
struct user *user;
+ size_t bodypos; /* for endpage() */
+};
+
+struct pagetemplate {
+ char *title;
+ char **css;
+ char **scripts;
};
enum kcgi_err loadpagerequest(struct kfcgi *fcgi, struct pagedata *pd);
void freepagerequest(struct pagedata *pd);
+enum kcgi_err startpage(struct pagedata *pd, struct pagetemplate *t, enum khttp status);
+enum kcgi_err endpage(struct pagedata *pd, struct pagetemplate *t);
enum kcgi_err showpage(struct pagedata *pd, char **names,
enum kcgi_err (*functions[])(struct pagedata *), size_t len);
enum kcgi_err errorpage(struct pagedata *pd, enum khttp code);
diff --git a/pages/account.c b/pages/account.c
@@ -6,6 +6,12 @@
enum kcgi_err
pageaccount(struct pagedata *pd)
{
+ static char *css[] = { "css/main.css", NULL };
+ static struct pagetemplate template = {
+ "Account",
+ .css = css
+ };
+
enum kcgi_err status;
if (!pd->user)
@@ -18,7 +24,7 @@ pageaccount(struct pagedata *pd)
return errorpage(pd, KHTTP_500);
}
- if ((status = starthtmldoc(pd, KHTTP_200, "Account")) != KCGI_OK ||
+ if ((status = startpage(pd, &template, KHTTP_200)) != KCGI_OK ||
(status = htmlwithin(pd, KELEM_H1, "Account")) != KCGI_OK ||
(status = htmlwithin(pd, KELEM_H2, "Delete account")) != KCGI_OK ||
(status = htmlwithin(pd, KELEM_P, "Deleting an account is irreversible:"
@@ -41,5 +47,5 @@ pageaccount(struct pagedata *pd)
(status = khtml_closeelem(&pd->html, 1)) != KCGI_OK)
return status;
- return khtml_close(&pd->html);
+ return endpage(pd, &template);
}
diff --git a/pages/index.c b/pages/index.c
@@ -5,9 +5,15 @@
enum kcgi_err
pageindex(struct pagedata *pd)
{
+ static char *css[] = { "css/main.css", NULL };
+ struct pagetemplate template = {
+ "Timekeeper",
+ .css = css
+ };
+
enum kcgi_err status;
- if ((status = starthtmldoc(pd, KHTTP_200, "Timekeeper")) != KCGI_OK)
+ if ((status = startpage(pd, &template, KHTTP_200)) != KCGI_OK)
return status;
khtml_elem(&pd->html, KELEM_H1);
@@ -27,5 +33,5 @@ pageindex(struct pagedata *pd)
return status;
}
- return khtml_close(&pd->html);
+ return endpage(pd, &template);
}
diff --git a/pages/login.c b/pages/login.c
@@ -32,6 +32,12 @@ htmlinput(struct pagedata *pd, enum http_key field, char *type, int64_t minl, in
enum kcgi_err
pagelogin(struct pagedata *pd)
{
+ static char *css[] = { "css/main.css", NULL };
+ static struct pagetemplate template = {
+ "Login",
+ .css = css
+ };
+
enum kcgi_err status;
struct user *user = NULL;
char *fuser, *fpass;
@@ -62,7 +68,7 @@ pagelogin(struct pagedata *pd)
}
}
- if ((status = starthtmldoc(pd, KHTTP_200, "Login")) != KCGI_OK)
+ if ((status = startpage(pd, &template, KHTTP_200)) != KCGI_OK)
return status;
if ((status = htmlwithin(pd, KELEM_H1, "Login")) != KCGI_OK)
@@ -94,5 +100,5 @@ pagelogin(struct pagedata *pd)
(status = khtml_closeelem(&pd->html, 1)) != KCGI_OK)
return status;
- return khtml_close(&pd->html);
+ return endpage(pd, &template);
}
diff --git a/pages/main.c b/pages/main.c
@@ -299,6 +299,18 @@ gettf(char *tfs)
enum kcgi_err
pagemain(struct pagedata *pd)
{
+ static char *css[] = { "css/main.css", NULL };
+ static char *scripts[] = {
+ "scripts/localize.js",
+ "scripts/counter.js",
+ NULL
+ };
+ static struct pagetemplate template = {
+ "Timesheet",
+ .css = css,
+ .scripts = scripts
+ };
+
enum kcgi_err status;
enum time_field tf;
struct timesheet *times, *end;
@@ -316,7 +328,7 @@ pagemain(struct pagedata *pd)
return KCGI_SYSTEM;
}
- status = starthtmldoc(pd, KHTTP_200, "Timesheets");
+ status = startpage(pd, &template, KHTTP_200);
if (status != KCGI_OK)
return status;
@@ -356,5 +368,5 @@ pagemain(struct pagedata *pd)
(status = khtml_closeelem(&pd->html, 1)) != KCGI_OK)
return status;
- return khtml_close(&pd->html);
+ return endpage(pd, &template);
}
diff --git a/pages/util.c b/pages/util.c
@@ -11,38 +11,19 @@
#include "../key.h"
enum kcgi_err
-starthtmldoc(struct pagedata *pd, enum khttp code, char *title)
-{
- enum kcgi_err status;
-
- if ((status = khttp_head(&pd->req, kresps[KRESP_STATUS], "%s", khttps[code])) != KCGI_OK ||
- (status = khttp_head(&pd->req, kresps[KRESP_CONTENT_TYPE], "%s", kmimetypes[KMIME_TEXT_HTML])) != KCGI_OK ||
- (status = khttp_body(&pd->req)) != KCGI_OK ||
- (status = khtml_open(&pd->html, &pd->req, KHTML_PRETTY)) != KCGI_OK ||
- (status = khtml_elem(&pd->html, KELEM_DOCTYPE)) != KCGI_OK ||
- (status = khtml_elem(&pd->html, KELEM_HTML)) != KCGI_OK ||
- (status = khtml_elem(&pd->html, KELEM_HEAD)) != KCGI_OK ||
- (status = khtml_elem(&pd->html, KELEM_TITLE)) != KCGI_OK ||
- (status = khtml_puts(&pd->html, title)) != KCGI_OK ||
- (status = khtml_closeelem(&pd->html, 1)) != KCGI_OK ||
- (status = khtml_attr(&pd->html, KELEM_LINK,
- KATTR_HREF, "css/main.css", KATTR_REL, "stylesheet", KATTR__MAX)) != KCGI_OK ||
- (status = khtml_closeelem(&pd->html, 1)) != KCGI_OK ||
- (status = khtml_elem(&pd->html, KELEM_BODY) != KCGI_OK))
- return status;
- kcgi_writer_disable(&pd->req);
-
- return KCGI_OK;
-}
-
-enum kcgi_err
redirect(struct pagedata *pd, char *to, char *msg)
{
+ static char *css[] = { "css/main.css", NULL };
+ static struct pagetemplate template = {
+ "Redirect",
+ .css = css
+ };
+
enum kcgi_err status;
if ((status = khttp_head(&pd->req, kresps[KRESP_LOCATION], "%s", to)) != KCGI_OK)
return status;
- if ((status = starthtmldoc(pd, KHTTP_303, "Redirect")) != KCGI_OK)
+ if ((status = startpage(pd, &template, KHTTP_303)) != KCGI_OK)
return status;
if ((status = khtml_elem(&pd->html, KELEM_H1)) != KCGI_OK ||
(status = khtml_puts(&pd->html, msg)) != KCGI_OK ||
diff --git a/pages/util.h b/pages/util.h
@@ -1,2 +1 @@
-enum kcgi_err starthtmldoc(struct pagedata *pd, enum khttp code, char *title);
enum kcgi_err redirect(struct pagedata *pd, char *to, char *msg);