Welcome to little lamb

Code » qmdoc » commit e32870d

Add -T/--no-toc not to write a page's TOC

author Olivier Brunel
2023-01-02 13:02:46 UTC
committer Olivier Brunel
2023-01-04 15:10:17 UTC
parent f51fec07240b8c44dbec188b66f28068916605b9

Add -T/--no-toc not to write a page's TOC

Note that in that case the left side of the page will remain "empty"
due to our CSS, so a custom CSS to adjust is probably needed.

main.c +66 -48

diff --git a/main.c b/main.c
index ef3e7ea..5555294 100644
--- a/main.c
+++ b/main.c
@@ -25,6 +25,7 @@ enum {
     OPT_NO_CSS      = (1 << 0),
     OPT_INLINE_CSS  = (1 << 1),
     OPT_OVERWRITE   = (1 << 2),
+    OPT_NO_TOC      = (1 << 3),
 };
 
 enum {
@@ -330,39 +331,45 @@ enter_block(MD_BLOCKTYPE type, void *details, void *ctx_)
                 }
                 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>"))
+                        || !raw_str(ctx, "<main>"))
                     return ERR_PARSER_ENTER_BLOCK;
 
-                for (int i = 0; i < ctx->nb_pages; ++i) {
-                    if (!raw_str(ctx, "<li><a href=\"")
+                if (!(ctx->options & OPT_NO_TOC)) {
+                    if (!raw_str(ctx, "<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;
+                    for (int i = 0; i < ctx->nb_pages; ++i) {
+                        if (!raw_str(ctx, "<li><a href=\"")
                                 || !escape_text(ctx, str_file(i), strlen(str_file(i)))
                                 || !raw_str(ctx, "\">")
                                 || !escape_text(ctx, str_title(i), strlen(str_title(i)))
                                 || !raw_str(ctx, "</a>"))
-                        return ERR_PARSER_ENTER_BLOCK;
+                            return ERR_PARSER_ENTER_BLOCK;
 
-                    /* remember positions for TOC */
-                    if (i == ctx->cur_page) {
-                        /* where to include it */
-                        ctx->otoc = ctx->sa_out.len;
+                        /* remember positions for TOC */
+                        if (i == ctx->cur_page) {
+                            /* where to include it */
+                            ctx->otoc = ctx->sa_out.len;
 
-                        /* open it */
-                        ctx->doc.flags |= DOC_BUFFERING;
-                        if (!raw_str(ctx, "<ul>")) {
+                            /* open it */
+                            ctx->doc.flags |= DOC_BUFFERING;
+                            if (!raw_str(ctx, "<ul>")) {
+                                ctx->doc.flags &= ~DOC_BUFFERING;
+                                return ERR_PARSER_TOC;
+                            }
+                            ctx->toc_lvl = 1;
                             ctx->doc.flags &= ~DOC_BUFFERING;
-                            return ERR_PARSER_TOC;
                         }
-                        ctx->toc_lvl = 1;
-                        ctx->doc.flags &= ~DOC_BUFFERING;
                     }
+                    if (!raw_str(ctx, "</ul></nav></header>"))
+                        return ERR_PARSER_ENTER_BLOCK;
                 }
+
+                if (!raw_str(ctx, "<section>"))
+                    return ERR_PARSER_ENTER_BLOCK;
 #undef str_title
 #undef str_file
-
-                if (!raw_str(ctx, "</ul></nav></header><section>"))
-                        return ERR_PARSER_ENTER_BLOCK;
             }
             break;
 
@@ -426,16 +433,18 @@ enter_block(MD_BLOCKTYPE type, void *details, void *ctx_)
                     return ERR_PARSER_ENTER_BLOCK;
                 ctx->doc.flags |= DOC_HAS_TITLE | DOC_BUFFERING;
 
-                /* TOC */
-                for ( ; ctx->toc_lvl < d->level; ++ctx->toc_lvl) {
-                    if (!raw_str(ctx, "<ul>"))
-                        return ERR_PARSER_TOC;
-                }
-                for ( ; ctx->toc_lvl > d->level; --ctx->toc_lvl) {
-                    if (!raw_str(ctx, "</ul>"))
-                        return ERR_PARSER_TOC;
+                if (!(ctx->options & OPT_NO_TOC)) {
+                    /* TOC */
+                    for ( ; ctx->toc_lvl < d->level; ++ctx->toc_lvl) {
+                        if (!raw_str(ctx, "<ul>"))
+                            return ERR_PARSER_TOC;
+                    }
+                    for ( ; ctx->toc_lvl > d->level; --ctx->toc_lvl) {
+                        if (!raw_str(ctx, "</ul>"))
+                            return ERR_PARSER_TOC;
+                    }
+                    ctx->buf.salen = ctx->buf.sa.len;
                 }
-                ctx->buf.salen = ctx->buf.sa.len;
             }
             break;
 
@@ -603,17 +612,19 @@ leave_block(MD_BLOCKTYPE type, void *details, void *ctx_)
                         || !raw_str(ctx, ">"))
                     return ERR_PARSER_LEAVE_BLOCK;
 
-                /* TOC */
-                char toc[l];
-                memcpy(toc, s, l);
-                ctx->doc.flags |= DOC_BUFFERING;
-                if (!raw_str(ctx, "<li><a href=\"#")
-                        || !anchor(ctx, toc, l)
-                        || !raw_str(ctx, "\">")
-                        || !strip_tags(ctx, toc, l, 1)
-                        || !raw_str(ctx, "</a>"))
-                    return ERR_PARSER_TOC;
-                ctx->doc.flags &= ~DOC_BUFFERING;
+                if (!(ctx->options & OPT_NO_TOC)) {
+                    /* TOC */
+                    char toc[l];
+                    memcpy(toc, s, l);
+                    ctx->doc.flags |= DOC_BUFFERING;
+                    if (!raw_str(ctx, "<li><a href=\"#")
+                            || !anchor(ctx, toc, l)
+                            || !raw_str(ctx, "\">")
+                            || !strip_tags(ctx, toc, l, 1)
+                            || !raw_str(ctx, "</a>"))
+                        return ERR_PARSER_TOC;
+                    ctx->doc.flags &= ~DOC_BUFFERING;
+                }
             }
             break;
 
@@ -941,16 +952,18 @@ convert_page(struct ctx *ctx, int fddest)
                            buf);
     }
 
-    /* close TOC */
-    ctx->doc.flags |= DOC_BUFFERING;
-    for ( ; ctx->toc_lvl > 0; --ctx->toc_lvl) {
-        if (!raw_str(ctx, "</ul>")) {
-            char buf[UINT32_FMT];
-            buf[uint32_fmt(buf, (uint32) ERR_PARSER_TOC)] = '\0';
-            ret_strerr_warnwu2x(ERR_PARSER, "parser internal error ", buf);
+    if (!(ctx->options & OPT_NO_TOC)) {
+        /* close TOC */
+        ctx->doc.flags |= DOC_BUFFERING;
+        for ( ; ctx->toc_lvl > 0; --ctx->toc_lvl) {
+            if (!raw_str(ctx, "</ul>")) {
+                char buf[UINT32_FMT];
+                buf[uint32_fmt(buf, (uint32) ERR_PARSER_TOC)] = '\0';
+                ret_strerr_warnwu2x(ERR_PARSER, "parser internal error ", buf);
+            }
         }
+        ctx->doc.flags &= ~DOC_BUFFERING;
     }
-    ctx->doc.flags &= ~DOC_BUFFERING;
 
     /* write output : */
     if (    /* up to TOC position */
@@ -1064,6 +1077,7 @@ help(void)
          " -I, --inline-css             Use inline CSS instead of external files\n"
          " -l, --lang LNG               Set LNG as language attribute\n"
          " -o, --overwrite              Overwrite destination files if already exist\n"
+         " -T, --no-toc                 Don't write a TOC on each page\n"
          " -t, --title TITLE            Set TITLE as general (across all pages) title\n"
         );
 }
@@ -1107,10 +1121,11 @@ main (int argc, char *argv[])
         { "inline-css",     no_argument,        NULL,   'I' },
         { "lang",           no_argument,        NULL,   'l' },
         { "overwrite",      no_argument,        NULL,   'o' },
+        { "no-toc",         no_argument,        NULL,   'T' },
         { "title",          required_argument,  NULL,   't' },
         { NULL,             0,                  NULL,    0  },
     };
-    while ((c = getopt_long(argc, argv, "a:Cc:d:F:H:hIl:ot:", opts, NULL)) != -1) switch (c) {
+    while ((c = getopt_long(argc, argv, "a:Cc:d:F:H:hIl:oTt:", opts, NULL)) != -1) switch (c) {
         case 'a':
             ctx.doc.author = optarg;
             break;
@@ -1140,6 +1155,9 @@ main (int argc, char *argv[])
         case 'o':
             ctx.options |= OPT_OVERWRITE;
             break;
+        case 'T':
+            ctx.options |= OPT_NO_TOC;
+            break;
         case 't':
             ctx.doc.title = optarg;
             break;