Welcome to little lamb

Code » qmdoc » commit 2fb4892

Add -H/--header & -F/--footer

author Olivier Brunel
2023-01-02 11:15:01 UTC
committer Olivier Brunel
2023-01-04 15:10:17 UTC
parent c36aab68cc9cf3b9b764c78305c808d9a0e1d27f

Add -H/--header & -F/--footer

Allows to add custom HTML header and/or footer on all generated pages,
to customize output adding some site-wide general header/footer.

main.c +37 -4

diff --git a/main.c b/main.c
index ae787c9..b94596b 100644
--- a/main.c
+++ b/main.c
@@ -76,6 +76,8 @@ struct ctx {
         const char *title;
         const char *author;
         const char *lang;
+        size_t oheader;
+        size_t ofooter;
         int flags;
     } doc;
     struct {
@@ -329,7 +331,9 @@ enter_block(MD_BLOCKTYPE type, void *details, void *ctx_)
                         return ERR_PARSER_ENTER_BLOCK;
                     }
                 }
-                if (!raw_str(ctx, "</head><body><main><header><section><h1>")
+                if (!raw_str(ctx, "</head><body>")
+                        || (ctx->doc.oheader && !raw_str(ctx, ctx->sa.s + ctx->doc.oheader))
+                        || !raw_str(ctx, "<main><header><section><h1>")
                         || !escape_text(ctx, ctx->doc.title, strlen(ctx->doc.title))
                         || !raw_str(ctx, "</h1></section><nav><ul>"))
                     return ERR_PARSER_ENTER_BLOCK;
@@ -538,7 +542,9 @@ leave_block(MD_BLOCKTYPE type, void *details, void *ctx_)
                     || !escape_text(ctx, ctx->doc.author, strlen(ctx->doc.author))
                     || !raw_str(ctx, "<br>"
                                 "<span class=\"generated\">Generated with qmdoc</span>"
-                                "</footer></section></main></body></html>"))
+                                "</footer></section></main>")
+                    || (ctx->doc.ofooter && !raw_str(ctx, ctx->sa.s + ctx->doc.ofooter))
+                    || !raw_str(ctx, "</body></html>"))
                 return ERR_PARSER_LEAVE_BLOCK;
             break;
 
@@ -1054,6 +1060,8 @@ help(void)
     outh(" -a, --author AUTHOR          Set AUTHOR as author (in meta in footer)\n"
          " -C, --no-css                 Do not use CSS\n"
          " -d, --destdir DIR            Write files into DIR\n"
+         " -F, --footer FILE            Insert FILE as common footer\n"
+         " -H, --header FILE            Insert FILE as common header\n"
          " -h, --help                   Show this help screen and exit\n"
          " -I, --inline-css             Use inline CSS instead of external files\n"
          " -l, --lang LNG               Set LNG as language attribute\n"
@@ -1076,6 +1084,8 @@ main (int argc, char *argv[])
     else PROG = argv[0];
 
     char *destdir = ".";
+    const char *footer = NULL;
+    const char *header = NULL;
     struct ctx ctx = {
         .options = 0,
         .sa = STRALLOC_ZERO,
@@ -1092,6 +1102,8 @@ main (int argc, char *argv[])
         { "author",         required_argument,  NULL,   'a' },
         { "no-css",         no_argument,        NULL,   'C' },
         { "destdir",        required_argument,  NULL,   'd' },
+        { "footer",         required_argument,  NULL,   'F' },
+        { "header",         required_argument,  NULL,   'H' },
         { "help",           no_argument,        NULL,   'h' },
         { "inline-css",     no_argument,        NULL,   'I' },
         { "lang",           no_argument,        NULL,   'l' },
@@ -1099,7 +1111,7 @@ main (int argc, char *argv[])
         { "title",          required_argument,  NULL,   't' },
         { NULL,             0,                  NULL,    0  },
     };
-    while ((c = getopt_long(argc, argv, "a:Cd:hIl:ot:", opts, NULL)) != -1) switch (c) {
+    while ((c = getopt_long(argc, argv, "a:Cd:F:H:hIl:ot:", opts, NULL)) != -1) switch (c) {
         case 'a':
             ctx.doc.author = optarg;
             break;
@@ -1109,6 +1121,12 @@ main (int argc, char *argv[])
         case 'd':
             destdir = optarg;
             break;
+        case 'F':
+            footer = optarg;
+            break;
+        case 'H':
+            header = optarg;
+            break;
         case 'h':
             help();
         case 'I':
@@ -1137,7 +1155,7 @@ main (int argc, char *argv[])
     ctx.pages = pages;
     ctx.nb_pages = sizeof(pages) / sizeof(*pages);
 
-    outse("Scanning files...");
+    outse("Scanning pages...");
     for (int i = optind; i < argc; ++i) {
         const char *file = argv[i];
         size_t len = strlen(file);
@@ -1153,6 +1171,21 @@ main (int argc, char *argv[])
         load_page_from_file(file, &pages[i - optind], &ctx.sa);
     }
 
+    if (header || footer) {
+        outse("Loading files...");
+
+        if (header) {
+            ctx.doc.oheader = ctx.sa.len;
+            if (!openreadfileclose(header, &ctx.sa, 0) || !stralloc_0(&ctx.sa))
+                strerr_diefu3sys(-ERR_IO, "load data from '", header, "'");
+        }
+        if (footer) {
+            ctx.doc.ofooter = ctx.sa.len;
+            if (!openreadfileclose(footer, &ctx.sa, 0) || !stralloc_0(&ctx.sa))
+                strerr_diefu3sys(-ERR_IO, "load data from '", footer, "'");
+        }
+    }
+
     if (!(ctx.options & OPT_NO_CSS)) {
         outs((ctx.options & OPT_INLINE_CSS) ? "Loading" : "Copying");
         outse(" CSS files...");