diff options
author | WormHeamer | 2025-03-10 15:40:01 -0400 |
---|---|---|
committer | WormHeamer | 2025-03-10 15:40:01 -0400 |
commit | 913c7e3bc4a8ba2b9ec46e4cd33286c713968f0b (patch) | |
tree | e82192a7e2d870f7a810a2908a3dde12c464f15f | |
parent | 9ab6a07efd2b89b01020470c17b3b9341f391faf (diff) |
add figure support
-rw-r--r-- | main.c | 124 |
1 files changed, 89 insertions, 35 deletions
diff --git a/main.c b/main.c index 553ed06..267c56f 100644 --- a/main.c +++ b/main.c @@ -88,6 +88,7 @@ typedef enum { LN_PAR, LN_CODE, LN_LINK, + LN_IMG, LN_BQUOT, LN_ULIST, LN_OLIST, @@ -99,7 +100,7 @@ typedef enum { typedef struct Line Line; struct Line { - Str txt; + Str txt, url; Line *next; }; @@ -148,6 +149,64 @@ LineType classify_line(Str line, LineType prev) { } } +int has_image_ext(Str url) { + return str_ends(url, S(".png")) + || str_ends(url, S(".jpg")) + || str_ends(url, S(".jpeg")) + || str_ends(url, S(".webp")); +} + +/* can change the line type based on parsing */ +LineType line_init(Line *l, Str txt, LineType t) { + Cut c; + switch (t) { + case LN_LINK: + c = str_cut(str_trim(str_skip(txt, 2)), ' '); + c.tail = str_trim(c.tail); + l->url = c.head; + l->txt = c.tail.n > 0 ? c.tail : c.head; + return has_image_ext(l->url) ? LN_IMG : LN_LINK; + case LN_HDR1: + l->txt = str_trim(str_skip(txt, 1)); + break; + case LN_HDR2: + l->txt = str_trim(str_skip(txt, 2)); + break; + case LN_HDR3: + l->txt = str_trim(str_skip(txt, 3)); + break; + case LN_ULIST: + l->txt = str_skip(txt, 2); + break; + case LN_OLIST: + l->txt = str_trim(str_cut(l->txt, '.').tail); + break; + case LN_BQUOT: + l->txt = str_trim(str_skip(txt, 1)); + break; + default: + l->txt = txt; + break; + } + return t; +} + +Block *blk_push(BlockList *blk, Line **lptr, LineType t, Arena *perm) { + if (blk->cap <= blk->len) { + size_t c = blk->cap; + if (!c) c = 16; + while (c <= blk->len) c <<= 1; + blk->data = resize(perm, blk->data, + blk->cap, c); + blk->cap = c; + } + Block *b = &blk->data[blk->len++]; + b->type = t; + b->lines = NULL; + *lptr = NULL; + return b; +} + BlockList blk_gather(Str src, Arena *perm) { Str line; LineType last = LN_NONE; @@ -160,25 +219,18 @@ BlockList blk_gather(Str src, Arena *perm) { } else if (t == LN_CODE) { last = LN_CODE; } else { - if (blk.len < 1 || t != blk.data[blk.len-1].type) { - if (blk.cap <= blk.len) { - size_t c = blk.cap; - if (!c) c = 16; - while (c <= blk.len) c <<= 1; - blk.data = resize(perm, blk.data, - blk.cap, c); - blk.cap = c; - } - Block *b = &blk.data[blk.len++]; - b->type = t; - b->lines = NULL; - lptr = NULL; + Block *b = blk.len > 0 ? &blk.data[blk.len-1] : NULL; + if (!b || t != b->type) { + b = blk_push(&blk, &lptr, t, perm); } Line *l = new(perm, Line); - l->txt = line; + LineType nt = line_init(l, line, t); + if (b->type != nt) { + if (b->lines) b = blk_push(&blk, &lptr, nt, perm); + else b->type = nt; + } if (lptr) lptr->next = l; lptr = l; - Block *b = &blk.data[blk.len-1]; if (!b->lines) b->lines = lptr; } last = t; @@ -212,42 +264,51 @@ void str_cat_blk(Str *out, Block *blk, Arena *perm, Arena *scratch) { case LN_LINK: Os("<ul>\n"); for (Line *l = blk->lines; l; l = l->next) { - Cut c = str_cut(str_trim(str_skip(l->txt, 2)), ' '); - Str url = c.head, txt = c.tail.n > 0 ? c.tail : c.head; Os("<li><a href="); - str_cat_uri(out, str_contains(url, S("://")) ? url : - str_replace_end(url, S(".gmi"), - S(".html"), scratch), perm); - Ot(">", txt, "</a></li>\n"); + str_cat_uri(out, str_contains(l->url, S("://")) + ? l->url + : str_replace_end(l->url, + S(".gmi"), S(".html"), + scratch), perm); + Ot(">", l->txt, "</a></li>\n"); } Os("</ul>"); break; + case LN_IMG: + for (Line *l = blk->lines; l; l = l->next) { + Os("<figure>\n"); + Ot("<figcaption>", l->txt, "</figcaption>\n<img src="); + str_cat_uri(out, l->url, perm); + Os(">\n</figcaption>"); + if (l->next) Os("\n"); + } + break; case LN_BQUOT: Os("<blockquote>"); for (Line *l = blk->lines; l; l = l->next) { - O(str_trim(str_skip(l->txt, 1))); + O(l->txt); if (l->next) Os("<br>\n"); } Os("<blockquote>"); break; case LN_ULIST: Os("<ul>\n"); - Otl("<li>", str_skip(l->txt, 2), "</li>\n"); + Otl("<li>", l->txt, "</li>\n"); Os("<ul>"); break; case LN_OLIST: Os("<ol>\n"); - Otl("<li>", str_trim(str_cut(l->txt, '.').tail), "</li>\n"); + Otl("<li>", l->txt, "</li>\n"); Os("<ol>"); break; case LN_HDR1: - Otl("<h1>", str_trim(str_skip(l->txt,1)), "</h1>"); + Otl("<h1>", l->txt, "</h1>"); break; case LN_HDR2: - Otl("<h2>", str_trim(str_skip(l->txt,2)), "</h2>"); + Otl("<h2>", l->txt, "</h2>"); break; case LN_HDR3: - Otl("<h3>", str_trim(str_skip(l->txt,3)), "</h3>"); + Otl("<h3>", l->txt, "</h3>"); break; default: case LN_PAR: @@ -262,13 +323,6 @@ void str_cat_blk(Str *out, Block *blk, Arena *perm, Arena *scratch) { Os("\n"); } -int has_image_ext(Str url) { - return str_ends(url, S(".png")) - || str_ends(url, S(".jpg")) - || str_ends(url, S(".jpeg")) - || str_ends(url, S(".webp")); -} - int wdoc(FILE *f, Doc **dp, Arena *perm, Arena *scratch) { Str buf; if (read_all(f, &buf, scratch)) return -1; |