author | Olivier Brunel
<jjk@jjacky.com> 2023-01-02 17:38:12 UTC |
committer | Olivier Brunel
<jjk@jjacky.com> 2023-01-04 15:10:17 UTC |
parent | b1cb6b27d2cc6f14fa3a4b8cf5f3c7b9326a446d |
base.htm | +4 | -0 |
dark.css | +6 | -0 |
light.css | +6 | -0 |
main.c | +38 | -3 |
struct.css | +22 | -0 |
diff --git a/base.htm b/base.htm index bec0bba..d91dd33 100644 --- a/base.htm +++ b/base.htm @@ -223,6 +223,10 @@ int main(int argc, char **argv) </div> </p> </section> + <section id="navbuttons"> + <a class="prev" href="#" title="Previous Title">Previous</a> + <a class="next" href="#" title="Next Title">Next</a> + </section> <footer> Copyright © 2022 Author Name - All Rights Reserved <br> diff --git a/dark.css b/dark.css index 7474f9a..caf4887 100644 --- a/dark.css +++ b/dark.css @@ -91,6 +91,12 @@ main div.box.note > :first-child { background: #575656; } + main #navbuttons a { + background: #9f9d1b; + border: 1px solid #232323; + color: inherit; + box-shadow: inset 0 1px 2px -1px hsla(0,0%,100%,.5),inset 0 -2px 0 0 #232323; + } main footer { border-top: 2px solid #515151; } diff --git a/light.css b/light.css index 63c4eb2..bfd9860 100644 --- a/light.css +++ b/light.css @@ -89,6 +89,12 @@ main div.box.note { main div.box.note > :first-child { background: #5c5353; } +main #navbuttons a { + background: #f0efb6; + border: 1px solid #232323; + color: inherit; + box-shadow: inset 0 1px 2px -1px hsla(0,0%,100%,.5),inset 0 -2px 0 0 #232323; +} main footer { border-top: 1px solid #979518; } diff --git a/main.c b/main.c index e45dce8..522dd80 100644 --- a/main.c +++ b/main.c @@ -26,6 +26,7 @@ enum { OPT_INLINE_CSS = (1 << 1), OPT_OVERWRITE = (1 << 2), OPT_NO_TOC = (1 << 3), + OPT_BUTTONS = (1 << 4), }; enum { @@ -549,8 +550,37 @@ leave_block(MD_BLOCKTYPE type, void *details, void *ctx_) struct tm tm; localtime_r(&ts.tv_sec, &tm); year[uint32_fmt(year, (uint32) 1900 + tm.tm_year)] = '\0'; - if (((ctx->doc.flags & DOC_HAS_TITLE) && !raw_str(ctx, "</section>")) - || !raw_str(ctx, "<footer>Copyright © ") + if ((ctx->doc.flags & DOC_HAS_TITLE) && !raw_str(ctx, "</section>")) + return ERR_PARSER_LEAVE_BLOCK; + if (ctx->options & OPT_BUTTONS) { +#define str_title(i) ctx->sa.s + ctx->pages[i].titleoff +#define str_file(i) ctx->sa.s + ctx->pages[i].fileoff + if (!raw_str(ctx, "<section id=\"navbuttons\">")) + return ERR_PARSER_LEAVE_BLOCK; + if (ctx->cur_page > 0 + && (!raw_str(ctx, "<a class=\"prev\" href=\"") + || !escape_text(ctx, str_file(ctx->cur_page - 1), + strlen(str_file(ctx->cur_page - 1))) + || !raw_str(ctx, "\" title=\"") + || !escape_text(ctx, str_title(ctx->cur_page - 1), + strlen(str_title(ctx->cur_page - 1))) + || !raw_str(ctx, "\">Previous</a>"))) + return ERR_PARSER_LEAVE_BLOCK; + if (ctx->cur_page < ctx->nb_pages - 1 + && (!raw_str(ctx, "<a class=\"next\" href=\"") + || !escape_text(ctx, str_file(ctx->cur_page + 1), + strlen(str_file(ctx->cur_page + 1))) + || !raw_str(ctx, "\" title=\"") + || !escape_text(ctx, str_title(ctx->cur_page + 1), + strlen(str_title(ctx->cur_page + 1))) + || !raw_str(ctx, "\">Next</a>"))) + return ERR_PARSER_LEAVE_BLOCK; + if (!raw_str(ctx, "</section>")) + return ERR_PARSER_LEAVE_BLOCK; +#undef str_file +#undef str_title + } + if (!raw_str(ctx, "<footer>Copyright © ") || !raw_str(ctx, year) || !raw_str(ctx, " ") || !escape_text(ctx, ctx->doc.author, strlen(ctx->doc.author)) @@ -1077,6 +1107,7 @@ static void help(void) { outh(" -a, --author AUTHOR Set AUTHOR as author (in meta in footer)\n" + " -b, --buttons Put Previous & Next buttons on pages\n" " -C, --no-css Do not use CSS (still process --css if any)\n" " -c, --css FILE Add FILE as additional CSS\n" " -d, --destdir DIR Write files into DIR\n" @@ -1121,6 +1152,7 @@ main (int argc, char *argv[]) int c; struct option opts[] = { { "author", required_argument, NULL, 'a' }, + { "buttons", no_argument, NULL, 'b' }, { "no-css", no_argument, NULL, 'C' }, { "css", required_argument, NULL, 'c' }, { "destdir", required_argument, NULL, 'd' }, @@ -1134,10 +1166,13 @@ main (int argc, char *argv[]) { "title", required_argument, NULL, 't' }, { NULL, 0, NULL, 0 }, }; - while ((c = getopt_long(argc, argv, "a:Cc:d:F:H:hIl:oTt:", opts, NULL)) != -1) switch (c) { + while ((c = getopt_long(argc, argv, "a:bCc:d:F:H:hIl:oTt:", opts, NULL)) != -1) switch (c) { case 'a': ctx.doc.author = optarg; break; + case 'b': + ctx.options |= OPT_BUTTONS; + break; case 'C': ctx.options |= OPT_NO_CSS; break; diff --git a/struct.css b/struct.css index 4d0a791..a7b4432 100644 --- a/struct.css +++ b/struct.css @@ -215,6 +215,28 @@ main div.box div.box { width: 90%; margin: auto; } +main #navbuttons { + height: 23px; +} +main #navbuttons a { + border-radius: 4px; + padding: 4px 12px 8px; + text-align: center; + font-size: 100%; + cursor: pointer; + text-decoration: none; + user-select: none; +} +main #navbuttons a.prev::before { + content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAANlBMVEUAAABAQEBAQEBAQEBAQEBAQEBAQEBBQUFAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAWW5SEAAAAEnRSTlMA/fC9r2kXAjMN34F3ZlUu6B40Y5wGAAAAVElEQVQY08XPSw6AIAwEUIbS8lFE739Zq6luGtbM8iXTTMOCZGECiCX/MhIQTyCNz+SRrUc1MWKVvR5KYCN6pUFDRtqq4Sql9IYJ+aI/70f4qdOHblOhAuUcC5KnAAAAAElFTkSuQmCC); +} +main #navbuttons a.next { + float: right; + margin-top: -4px; +} +main #navbuttons a.next::after { + content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASBAMAAACk4JNkAAAAJFBMVEUAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEC4lvDfAAAAC3RSTlMAx711ZjlFPh3zLASjkrYAAABDSURBVAjXY6AUsGhvcgAzOKR3797YAGIx7t5mvVsAxPLevZ159xYQS3v3zgLrTSDW7tTQBcy7ESyELEIHwhSEyQjbAAH1HsMY8tCHAAAAAElFTkSuQmCC); +} main footer { padding: 8px 23px; margin: 0 -23px;