Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package lowdown for openSUSE:Factory checked in at 2024-12-08 11:37:16 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/lowdown (Old) and /work/SRC/openSUSE:Factory/.lowdown.new.21547 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "lowdown" Sun Dec 8 11:37:16 2024 rev:4 rq:1228812 version:1.3.1 Changes: -------- --- /work/SRC/openSUSE:Factory/lowdown/lowdown.changes 2024-12-02 16:59:34.358304519 +0100 +++ /work/SRC/openSUSE:Factory/.lowdown.new.21547/lowdown.changes 2024-12-08 11:38:18.356551662 +0100 @@ -1,0 +2,14 @@ +Fri Dec 06 15:58:50 UTC 2024 - scott.bradn...@suse.com + +- Update to version 1.3.1: + * Version bump. + * Internal template documentation. + * Add --template functionality to -tlatex. + * Only use --template along with -s. + * Update docs. + * Add regressions and fix corner case. + * Add boolean operators and() and or(). + * Add latex escaping to template. + * Rename hesc and move latex escape. + +------------------------------------------------------------------- Old: ---- lowdown-1.3.0.tar.gz New: ---- lowdown-1.3.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ lowdown.spec ++++++ --- /var/tmp/diff_new_pack.HBy9N9/_old 2024-12-08 11:38:18.780569278 +0100 +++ /var/tmp/diff_new_pack.HBy9N9/_new 2024-12-08 11:38:18.780569278 +0100 @@ -20,7 +20,7 @@ #%%global version_string VERSION_1_1_0 Name: lowdown -Version: 1.3.0 +Version: 1.3.1 Release: 0 Summary: Simple markdown translator License: ISC ++++++ _service ++++++ --- /var/tmp/diff_new_pack.HBy9N9/_old 2024-12-08 11:38:18.808570441 +0100 +++ /var/tmp/diff_new_pack.HBy9N9/_new 2024-12-08 11:38:18.812570607 +0100 @@ -2,7 +2,7 @@ <service name="obs_scm" mode="manual"> <param name="url">https://github.com/kristapsdz/lowdown</param> <param name="scm">git</param> - <param name="revision">VERSION_1_3_0</param> + <param name="revision">VERSION_1_3_1</param> <param name="versionformat">@PARENT_TAG@</param> <!-- If we ever have to package a snapshot, use this format pattern: <param name="versionformat">@PARENT_TAG@+git@TAG_OFFSET@.%h</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.HBy9N9/_old 2024-12-08 11:38:18.840571770 +0100 +++ /var/tmp/diff_new_pack.HBy9N9/_new 2024-12-08 11:38:18.840571770 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/kristapsdz/lowdown</param> - <param name="changesrevision">7f0c33949a20c7fbdad3a8f479ca28c17b5f7b25</param></service></servicedata> + <param name="changesrevision">6c42fe9655f5db3a0d7eb1ccaa3c1830f211481a</param></service></servicedata> (No newline at EOF) ++++++ lowdown-1.3.0.tar.gz -> lowdown-1.3.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/Makefile new/lowdown-1.3.1/Makefile --- old/lowdown-1.3.0/Makefile 2024-12-01 08:26:15.000000000 +0100 +++ new/lowdown-1.3.1/Makefile 2024-12-06 04:08:10.000000000 +0100 @@ -10,7 +10,7 @@ # while libraries have well-defined semantics of semver change, programs # do not. Let the library guide our versioning until a better way is # thought out. -VERSION = 1.3.0 +VERSION = 1.3.1 # This is the major number of VERSION. It might later become # MAJOR.MINOR, if the library moves a lot. LIBVER = 1 @@ -23,6 +23,7 @@ html.o \ html_escape.o \ latex.o \ + latex_escape.o \ library.o \ libdiff.o \ nroff.o \ @@ -86,6 +87,7 @@ html.c \ html_escape.c \ latex.c \ + latex_escape.c \ libdiff.c \ library.c \ main.c \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/extern.h new/lowdown-1.3.1/extern.h --- old/lowdown-1.3.0/extern.h 2024-12-01 08:26:15.000000000 +0100 +++ new/lowdown-1.3.1/extern.h 2024-12-06 04:08:10.000000000 +0100 @@ -70,9 +70,14 @@ ssize_t halink_url(size_t *, struct lowdown_buf *, char *, size_t, size_t); ssize_t halink_www(size_t *, struct lowdown_buf *, char *, size_t, size_t); -int hesc_attr(struct lowdown_buf *, const char *, size_t); -int hesc_href(struct lowdown_buf *, const char *, size_t); -int hesc_html(struct lowdown_buf *, const char *, size_t, int, int, int); +int lowdown_html_esc(struct lowdown_buf *, + const char *, size_t, int, int, int); +int lowdown_html_esc_attr(struct lowdown_buf *, + const char *, size_t); +int lowdown_html_esc_href(struct lowdown_buf *, + const char *, size_t); +int lowdown_latex_esc(struct lowdown_buf *, + const char *, size_t); char *rcsdate2str(const char *); char *rcsauthor2str(const char *); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/html.c new/lowdown-1.3.1/html.c --- old/lowdown-1.3.0/html.c 2024-12-01 08:26:15.000000000 +0100 +++ new/lowdown-1.3.1/html.c 2024-12-06 04:08:10.000000000 +0100 @@ -55,7 +55,7 @@ const struct html *st) { - return hesc_html(ob, source, length, + return lowdown_html_esc(ob, source, length, st->flags & LOWDOWN_HTML_OWASP, 0, st->flags & LOWDOWN_HTML_NUM_ENT); } @@ -64,7 +64,7 @@ * See escape_html(). */ static int -escape_htmlb(struct lowdown_buf *ob, +escape_htmlb(struct lowdown_buf *ob, const struct lowdown_buf *in, const struct html *st) { @@ -77,11 +77,11 @@ * Return zero on failure, non-zero on success. */ static int -escape_literal(struct lowdown_buf *ob, +escape_literal(struct lowdown_buf *ob, const struct lowdown_buf *in, const struct html *st) { - return hesc_html(ob, in->data, in->size, + return lowdown_html_esc(ob, in->data, in->size, st->flags & LOWDOWN_HTML_OWASP, 1, st->flags & LOWDOWN_HTML_NUM_ENT); } @@ -95,7 +95,7 @@ const struct html *st) { - return hesc_href(ob, in->data, in->size); + return lowdown_html_esc_href(ob, in->data, in->size); } /* @@ -106,7 +106,7 @@ escape_attr(struct lowdown_buf *ob, const struct lowdown_buf *in) { - return hesc_attr(ob, in->data, in->size); + return lowdown_html_esc_attr(ob, in->data, in->size); } static int @@ -119,7 +119,7 @@ } static int -rndr_autolink(struct lowdown_buf *ob, +rndr_autolink(struct lowdown_buf *ob, const struct rndr_autolink *parm, const struct html *st) { @@ -142,8 +142,8 @@ */ if (hbuf_strprefix(&parm->link, "mailto:")) { - if (!escape_html(ob, - parm->link.data + 7, + if (!escape_html(ob, + parm->link.data + 7, parm->link.size - 7, st)) return 0; } else { @@ -155,7 +155,7 @@ } static int -rndr_blockcode(struct lowdown_buf *ob, +rndr_blockcode(struct lowdown_buf *ob, const struct rndr_blockcode *parm, const struct html *st) { if (!newline(ob)) @@ -230,7 +230,7 @@ if (!newline(ob)) return 0; - if (param->type == BLOCKQUOTE_REGULAR || !(st->flags & + if (param->type == BLOCKQUOTE_REGULAR || !(st->flags & (LOWDOWN_HTML_CALLOUT_GFM|LOWDOWN_HTML_CALLOUT_MDN))) return HBUF_PUTSL(ob, "<blockquote>\n") && hbuf_putb(ob, content) && @@ -454,7 +454,7 @@ return 0; if (param->flags & HLIST_FL_ORDERED) { if (param->start > 1) { - if (!hbuf_printf(ob, + if (!hbuf_printf(ob, "<ol start=\"%zu\">\n", param->start)) return 0; } else { @@ -489,7 +489,7 @@ n->parent != NULL && n->parent->parent != NULL && n->parent->parent->type == LOWDOWN_DEFINITION && - (n->parent->parent->rndr_definition.flags & + (n->parent->parent->rndr_definition.flags & HLIST_FL_BLOCK)) || (!(n->rndr_listitem.flags & HLIST_FL_DEF) && n->parent != NULL && @@ -552,7 +552,7 @@ if (content->size == 0) return 1; while (i < content->size && - isspace((unsigned char)content->data[i])) + isspace((unsigned char)content->data[i])) i++; if (i == content->size) return 1; @@ -565,7 +565,7 @@ if (st->flags & LOWDOWN_HTML_HARD_WRAP) { for ( ; i < content->size; i++) { org = i; - while (i < content->size && + while (i < content->size && content->data[i] != '\n') i++; @@ -584,7 +584,7 @@ return 0; } } else { - if (!hbuf_put(ob, + if (!hbuf_put(ob, content->data + i, content->size - i)) return 0; } @@ -603,9 +603,9 @@ if ((st->flags & LOWDOWN_HTML_ESCAPE)) return escape_htmlb(ob, ¶m->text, st); - /* + /* * FIXME: Do we *really* need to trim the HTML? How does that - * make a difference? + * make a difference? */ sz = param->text.size; @@ -662,7 +662,7 @@ * that as a cap to the size. */ - if (param->dims.size && + if (param->dims.size && param->dims.size < sizeof(dimbuf) - 1) { memset(dimbuf, 0, sizeof(dimbuf)); memcpy(dimbuf, param->dims.data, param->dims.size); @@ -861,14 +861,14 @@ /* Insert anchor at the end of first paragraph block. */ while ((i + 3) < content->size) { - if (content->data[i++] != '<') + if (content->data[i++] != '<') continue; - if (content->data[i++] != '/') + if (content->data[i++] != '/') continue; - if (content->data[i++] != 'p' && - content->data[i] != 'P') + if (content->data[i++] != 'p' && + content->data[i] != 'P') continue; - if (content->data[i] != '>') + if (content->data[i] != '>') continue; i -= 3; pfound = 1; @@ -886,7 +886,7 @@ "↩" "</a>", num)) return 0; - if (!hbuf_put(ob, + if (!hbuf_put(ob, content->data + i, content->size - i)) return 0; } else { @@ -918,14 +918,14 @@ if ((st->foots[st->footsz++] = hbuf_dup(content)) == NULL) return 0; - return hbuf_printf(ob, + return hbuf_printf(ob, "<sup id=\"fnref%zu\">" "<a href=\"#fn%zu\" rel=\"footnote\">" "%zu</a></sup>", num, num, num); } static int -rndr_math(struct lowdown_buf *ob, const struct rndr_math *param, +rndr_math(struct lowdown_buf *ob, const struct rndr_math *param, const struct html *st) { @@ -1005,12 +1005,12 @@ if (!hbuf_puts(ob, starttag)) return 0; - if (attr && !hesc_attr(ob, start, sz)) + if (attr && !lowdown_html_esc_attr(ob, start, sz)) return 0; - else if (href && !hesc_href(ob, start, sz)) + else if (href && !lowdown_html_esc_href(ob, start, sz)) return 0; - else if (!attr && !href && !hesc_html(ob, start, sz, - st->flags & LOWDOWN_HTML_OWASP, 0, + else if (!attr && !href && !lowdown_html_esc(ob, start, + sz, st->flags & LOWDOWN_HTML_OWASP, 0, st->flags & LOWDOWN_HTML_NUM_ENT)) return 0; if (!hbuf_puts(ob, endtag)) @@ -1029,15 +1029,15 @@ const struct lowdown_meta *m; const char *author = NULL, *title = NULL, *affil = NULL, *date = NULL, - *copy = NULL, *rcsauthor = NULL, + *copy = NULL, *rcsauthor = NULL, *rcsdate = NULL, *css = NULL, *script = NULL, *header = NULL, *lang = NULL; - if (st->templ != NULL) - return lowdown_template(st->templ, content, ob, mq); - else if (!(st->flags & LOWDOWN_STANDALONE)) + if (!(st->flags & LOWDOWN_STANDALONE)) return hbuf_putb(ob, content); + if (st->templ != NULL) + return lowdown_template(st->templ, content, ob, mq); TAILQ_FOREACH(m, mq, entries) if (strcasecmp(m->key, "author") == 0) @@ -1074,13 +1074,13 @@ return 0; if (lang != NULL && (!HBUF_PUTSL(ob, "<html lang=\"") || - !hesc_attr(ob, lang, strlen(lang)) || + !lowdown_html_esc_attr(ob, lang, strlen(lang)) || !HBUF_PUTSL(ob, "\">\n"))) return 0; else if (lang == NULL && !HBUF_PUTSL(ob, "<html>\n")) return 0; - if (!HBUF_PUTSL(ob, + if (!HBUF_PUTSL(ob, "<head>\n" "<meta charset=\"utf-8\" />\n" "<meta name=\"viewport\" content=\"" @@ -1117,7 +1117,7 @@ return 0; if (!HBUF_PUTSL(ob, "content=\"")) return 0; - if (!hesc_attr(ob, date, strlen(date))) + if (!lowdown_html_esc_attr(ob, date, strlen(date))) return 0; if (!HBUF_PUTSL(ob, "\" />\n")) return 0; @@ -1134,7 +1134,7 @@ if (!HBUF_PUTSL(ob, "<title>")) return 0; if (title != NULL && - !hesc_html(ob, title, strlen(title), + !lowdown_html_esc(ob, title, strlen(title), st->flags & LOWDOWN_HTML_OWASP, 0, st->flags & LOWDOWN_HTML_NUM_ENT)) return 0; @@ -1164,7 +1164,7 @@ * Return zero on failure, non-zero on success. */ static int -rndr_meta(struct html *st, const struct lowdown_node *n, +rndr_meta(struct html *st, const struct lowdown_node *n, struct lowdown_metaq *mq) { struct lowdown_meta *m; @@ -1197,7 +1197,7 @@ { const struct lowdown_meta *m; const char *author = NULL, *title = NULL, - *date = NULL, *rcsauthor = NULL, + *date = NULL, *rcsauthor = NULL, *rcsdate = NULL; if (!(st->flags & LOWDOWN_HTML_TITLEBLOCK)) @@ -1231,7 +1231,7 @@ return 0; if (title != NULL && (!HBUF_PUTSL(ob, "<h1 class=\"title\">") || - !hesc_html(ob, title, strlen(title), + !lowdown_html_esc(ob, title, strlen(title), st->flags & LOWDOWN_HTML_OWASP, 0, st->flags & LOWDOWN_HTML_NUM_ENT) || !HBUF_PUTSL(ob, "</h1>\n"))) @@ -1242,7 +1242,7 @@ return 0; if (date != NULL && (!HBUF_PUTSL(ob, "<p class=\"date\">") || - !hesc_html(ob, date, strlen(date), + !lowdown_html_esc(ob, date, strlen(date), st->flags & LOWDOWN_HTML_OWASP, 0, st->flags & LOWDOWN_HTML_NUM_ENT) || !HBUF_PUTSL(ob, "</p>\n"))) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/html_escape.c new/lowdown-1.3.1/html_escape.c --- old/lowdown-1.3.0/html_escape.c 2024-12-01 08:26:15.000000000 +0100 +++ new/lowdown-1.3.1/html_escape.c 2024-12-06 04:08:10.000000000 +0100 @@ -22,7 +22,6 @@ # include <sys/queue.h> #endif -#include <assert.h> #include <stdint.h> #include <stdio.h> #include <string.h> @@ -143,7 +142,8 @@ * This is modelled after the main Markdown parser. */ int -hesc_attr(struct lowdown_buf *ob, const char *data, size_t size) +lowdown_html_esc_attr(struct lowdown_buf *ob, const char *data, + size_t size) { size_t i, mark; int rc; @@ -183,7 +183,8 @@ * Return zero on failure (memory), non-zero otherwise. */ int -hesc_href(struct lowdown_buf *ob, const char *data, size_t size) +lowdown_html_esc_href(struct lowdown_buf *ob, const char *data, + size_t size) { static const char hex_chars[] = "0123456789ABCDEF"; size_t i, mark; @@ -251,16 +252,17 @@ } /* - * Escape HTML. - * If "literal", we also want to escape some extra characters. + * Escape HTML (really XML). + * If "literal", also escape some extra characters. * If "secure", also escape characters as suggested by OWASP rules. + * FIXME: literal and secure do the same thing. * If "num", use only numeric escapes. * Does nothing if "size" is zero. * Return zero on failure (memory), non-zero otherwise. */ int -hesc_html(struct lowdown_buf *ob, const char *data, - size_t size, int secure, int literal, int num) +lowdown_html_esc(struct lowdown_buf *ob, const char *data, + size_t size, int secure, int literal, int num) { size_t i, mark; int max = 0, rc; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/latex.c new/lowdown-1.3.1/latex.c --- old/lowdown-1.3.0/latex.c 2024-12-01 08:26:15.000000000 +0100 +++ new/lowdown-1.3.1/latex.c 2024-12-06 04:08:10.000000000 +0100 @@ -32,77 +32,33 @@ #include "extern.h" struct latex { - unsigned int oflags; /* same as in lowdown_opts */ - struct hentryq headers_used; /* headers we've seen */ - ssize_t headers_offs; /* header offset */ - size_t footsz; /* current footnote */ + unsigned int oflags; /* same as in lowdown_opts */ + struct hentryq headers_used; /* headers we've seen */ + ssize_t headers_offs; /* header offset */ + size_t footsz; /* current footnote */ + const char *templ; /* output template */ }; /* - * Escape LaTeX special characters. - * Return zero on failure, non-zero on success. - */ -static int -rndr_escape_text(const struct latex *st, struct lowdown_buf *ob, - const char *data, size_t sz) -{ - size_t i; - - for (i = 0; i < sz; i++) - switch (data[i]) { - case '&': - case '%': - case '$': - case '#': - case '_': - case '{': - case '}': - if (!hbuf_putc(ob, '\\')) - return 0; - if (!hbuf_putc(ob, data[i])) - return 0; - break; - case '~': - if (!HBUF_PUTSL(ob, "\\textasciitilde{}")) - return 0; - break; - case '^': - if (!HBUF_PUTSL(ob, "\\textasciicircum{}")) - return 0; - break; - case '\\': - if (!HBUF_PUTSL(ob, "\\textbackslash{}")) - return 0; - break; - default: - if (!hbuf_putc(ob, data[i])) - return 0; - break; - } - - return 1; -} - -/* - * Like rndr_escape_text() but with a NUL-terminated string. + * Like lowdown_latex_esc() but with a NUL-terminated string. */ static int rndr_escape_string(const struct latex *st, struct lowdown_buf *ob, const char *data) { - return rndr_escape_text(st, ob, data, strlen(data)); + return lowdown_latex_esc(ob, data, strlen(data)); } /* - * Like rndr_escape_text() but with a buffer. + * Like lowdown_latex_esc() but with a buffer. */ static int rndr_escape(const struct latex *st, struct lowdown_buf *ob, const struct lowdown_buf *dat) { - return rndr_escape_text(st, ob, dat->data, dat->size); + return lowdown_latex_esc(ob, dat->data, dat->size); } static int @@ -377,8 +333,8 @@ else if (!loc && !HBUF_PUTSL(ob, "\\href{")) return 0; - if (loc && !rndr_escape_text - (st, ob, ¶m->link.data[1], param->link.size - 1)) + if (loc && !lowdown_latex_esc + (ob, ¶m->link.data[1], param->link.size - 1)) return 0; else if (!loc && !rndr_escape(st, ob, ¶m->link)) return 0; @@ -575,13 +531,13 @@ if (cp != NULL) { if (!HBUF_PUTSL(ob, "{")) return 0; - if (!rndr_escape_text - (st, ob, param->link.data, cp - param->link.data)) + if (!lowdown_latex_esc + (ob, param->link.data, cp - param->link.data)) return 0; if (!HBUF_PUTSL(ob, "}")) return 0; - if (!rndr_escape_text(st, ob, cp, - param->link.size - (cp - param->link.data))) + if (!lowdown_latex_esc + (ob, cp, param->link.size - (cp - param->link.data))) return 0; } else { if (!rndr_escape(st, ob, ¶m->link)) @@ -708,17 +664,8 @@ } static int -rndr_doc_footer(struct lowdown_buf *ob, const struct latex *st) -{ - - if (st->oflags & LOWDOWN_STANDALONE) - return HBUF_PUTSL(ob, "\\end{document}\n"); - return 1; -} - -static int -rndr_doc_header(const struct latex *st, struct lowdown_buf *ob, - const struct lowdown_metaq *mq) +rndr_root(const struct latex *st, struct lowdown_buf *ob, + const struct lowdown_metaq *mq, const struct lowdown_buf *content) { const struct lowdown_meta *m; const char *author = NULL, *title = NULL, @@ -727,7 +674,9 @@ *rcsdate = NULL, *header = NULL; if (!(st->oflags & LOWDOWN_STANDALONE)) - return 1; + return hbuf_putb(ob, content); + if (st->templ != NULL) + return lowdown_template(st->templ, content, ob, mq); TAILQ_FOREACH(m, mq, entries) if (strcasecmp(m->key, "author") == 0) @@ -834,7 +783,10 @@ !HBUF_PUTSL(ob, "\\maketitle\n")) return 0; - return 1; + if (!hbuf_putb(ob, content)) + return 0; + + return HBUF_PUTSL(ob, "\\end{document}\n"); } static int @@ -895,6 +847,9 @@ if (!rndr_blockcode(ob, &n->rndr_blockcode)) return 0; break; + case LOWDOWN_DOC_HEADER: + /* Don't output anything for this. */ + break; case LOWDOWN_BLOCKQUOTE: if (!rndr_blockquote(ob, tmp)) return 0; @@ -907,10 +862,6 @@ if (!rndr_definition_title(ob, tmp)) return 0; break; - case LOWDOWN_DOC_HEADER: - if (!rndr_doc_header(st, ob, mq)) - return 0; - break; case LOWDOWN_META: if (n->chng != LOWDOWN_CHNG_DELETE && !rndr_meta(st, n, mq)) @@ -1017,9 +968,7 @@ return 0; break; case LOWDOWN_ROOT: - if (!hbuf_putb(ob, tmp)) - return 0; - if (!rndr_doc_footer(ob, st)) + if (!rndr_root(st, ob, mq, tmp)) return 0; break; default: @@ -1067,6 +1016,7 @@ return NULL; p->oflags = opts == NULL ? 0 : opts->oflags; + p->templ = opts == NULL ? NULL : opts->templ; return p; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/latex_escape.c new/lowdown-1.3.1/latex_escape.c --- old/lowdown-1.3.0/latex_escape.c 1970-01-01 01:00:00.000000000 +0100 +++ new/lowdown-1.3.1/latex_escape.c 2024-12-06 04:08:10.000000000 +0100 @@ -0,0 +1,72 @@ +/* + * Copyright (c) Kristaps Dzonsons <krist...@bsd.lv> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "config.h" + +#if HAVE_SYS_QUEUE +# include <sys/queue.h> +#endif + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> + +#include "lowdown.h" +#include "extern.h" + +/* + * Escape LaTeX special characters. + * Return zero on failure (memory), non-zero on success. + */ +int +lowdown_latex_esc(struct lowdown_buf *ob, const char *data, size_t sz) +{ + size_t i; + + for (i = 0; i < sz; i++) + switch (data[i]) { + case '&': + case '%': + case '$': + case '#': + case '_': + case '{': + case '}': + if (!hbuf_putc(ob, '\\')) + return 0; + if (!hbuf_putc(ob, data[i])) + return 0; + break; + case '~': + if (!HBUF_PUTSL(ob, "\\textasciitilde{}")) + return 0; + break; + case '^': + if (!HBUF_PUTSL(ob, "\\textasciicircum{}")) + return 0; + break; + case '\\': + if (!HBUF_PUTSL(ob, "\\textbackslash{}")) + return 0; + break; + default: + if (!hbuf_putc(ob, data[i])) + return 0; + break; + } + + return 1; +} + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/man/lowdown-diff.1 new/lowdown-1.3.1/man/lowdown-diff.1 --- old/lowdown-1.3.0/man/lowdown-diff.1 2024-12-01 08:26:15.000000000 +0100 +++ new/lowdown-1.3.1/man/lowdown-diff.1 2024-12-06 04:08:10.000000000 +0100 @@ -200,7 +200,9 @@ .Sx Templates . This is experimental functionality. Currently only for -.Fl t Ns Ar html . +.Fl t Ns Ar html +and +.Fl t Ns Ar latex . .El .Pp What follows are per-output long options. @@ -853,21 +855,28 @@ The .Li initial value is one of the following: -.Bl -bullet -.It -a canonicalised metadata key -.It -.Li this -.Pq value of a current loop context -.It -.Li body -.Pq parsed input document body -.It -.Li meta(val) -to force accepting +.Bl -tag -width Ds +.It Li and(expression[,expression]*) +A non-empty list containing the value +.Li true +if all expressions evaluate to non-empty lists, otherwise an empty list. +An empty expression evaluates to an empty list. +.It canonicalised metadata key +The value for the given metadata key, if found, otherwise an empty list. +.It Li body +The parsed input document body. +.It Li meta(val) +Evaluate .Li val as a metadata key, even if it's a special variable like -.Li body +.Li body . +.It Li or(expression[,expression]*) +A non-empty list containing the value +.Li true +if one expression evaluates to non-empty lists, otherwise an empty list. +An empty expression evaluates to an empty list. +.It Li this +The value of a current loop context or an empty list. .El .Pp If a metadata key is not specified in the input, or if the anaphoric @@ -920,6 +929,11 @@ .Fl -template is not provided to .Fl t Ns Ar html . +.It Pa share/latex/default.latex +The default template used if +.Fl -template +is not provided to +.Fl t Ns Ar latex . .It Pa share/odt/styles.xml Default styles used when generating standalone .Fl t Ns Ar fodt diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/man/lowdown.1 new/lowdown-1.3.1/man/lowdown.1 --- old/lowdown-1.3.0/man/lowdown.1 2024-12-01 08:26:15.000000000 +0100 +++ new/lowdown-1.3.1/man/lowdown.1 2024-12-06 04:08:10.000000000 +0100 @@ -218,7 +218,9 @@ .Sx Templates . This is experimental functionality. Currently only for -.Fl t Ns Ar html . +.Fl t Ns Ar html +and +.Fl t Ns Ar latex . .El .Pp What follows are per-output long options. @@ -846,21 +848,28 @@ The .Li initial value is one of the following: -.Bl -bullet -.It -a canonicalised metadata key -.It -.Li this -.Pq value of a current loop context -.It -.Li body -.Pq parsed input document body -.It -.Li meta(val) -to force accepting +.Bl -tag -width Ds +.It Li and(expression[,expression]*) +A non-empty list containing the value +.Li true +if all expressions evaluate to non-empty lists, otherwise an empty list. +An empty expression evaluates to an empty list. +.It canonicalised metadata key +The value for the given metadata key, if found, otherwise an empty list. +.It Li body +The parsed input document body. +.It Li meta(val) +Evaluate .Li val as a metadata key, even if it's a special variable like -.Li body +.Li body . +.It Li or(expression[,expression]*) +A non-empty list containing the value +.Li true +if one expression evaluates to non-empty lists, otherwise an empty list. +An empty expression evaluates to an empty list. +.It Li this +The value of a current loop context or an empty list. .El .Pp If a metadata key is not specified in the input, or if the anaphoric @@ -913,6 +922,11 @@ .Fl -template is not provided to .Fl t Ns Ar html . +.It Pa share/latex/default.latex +The default template used if +.Fl -template +is not provided to +.Fl t Ns Ar latex . .It Pa share/odt/styles.xml Default styles used when generating standalone .Fl t Ns Ar fodt diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/man/lowdown.3 new/lowdown-1.3.1/man/lowdown.3 --- old/lowdown-1.3.0/man/lowdown.3 2024-12-01 08:26:15.000000000 +0100 +++ new/lowdown-1.3.1/man/lowdown.3 2024-12-06 04:08:10.000000000 +0100 @@ -554,6 +554,14 @@ .It Va size_t metaovrsz Number of pairs in .Va metaovr . +.It Va const char *templ +If +.Dv LOWDOWN_STANDALONE +is specified, this is set to the external template file or +.Dv NULL +to use internal templating. +This is only valid for output media supporting external templates; +otherwise, it may be ignored. .El .Pp Parsed metadata is held in key-value diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/odt.c new/lowdown-1.3.1/odt.c --- old/lowdown-1.3.0/odt.c 2024-12-01 08:26:15.000000000 +0100 +++ new/lowdown-1.3.1/odt.c 2024-12-06 04:08:10.000000000 +0100 @@ -909,7 +909,7 @@ if (author != NULL) { if (!HBUF_PUTSL(ob, "<dc:creator>")) return 0; - if (!hesc_html(ob, author, + if (!lowdown_html_esc(ob, author, strlen(author), 1, 0, 1)) return 0; if (!HBUF_PUTSL(ob, "</dc:creator>\n")) @@ -917,7 +917,7 @@ } if (!HBUF_PUTSL(ob, "<dc:date>")) return 0; - if (!hesc_html(ob, date, strlen(date), 1, 0, 1)) + if (!lowdown_html_esc(ob, date, strlen(date), 1, 0, 1)) return 0; if (!HBUF_PUTSL(ob, "</dc:date>\n")) return 0; @@ -974,7 +974,7 @@ if (title != NULL) { if (!HBUF_PUTSL(ob, "<dc:title>")) return 0; - if (!hesc_html(ob, title, strlen(title), 1, 0, 1)) + if (!lowdown_html_esc(ob, title, strlen(title), 1, 0, 1)) return 0; if (!HBUF_PUTSL(ob, "</dc:title>\n")) return 0; @@ -983,13 +983,13 @@ if (author != NULL) { if (!HBUF_PUTSL(ob, "<dc:creator>")) return 0; - if (!hesc_html(ob, author, strlen(author), 1, 0, 1)) + if (!lowdown_html_esc(ob, author, strlen(author), 1, 0, 1)) return 0; if (!HBUF_PUTSL(ob, "</dc:creator>\n")) return 0; if (!HBUF_PUTSL(ob, "<meta:initial-creator>")) return 0; - if (!hesc_html(ob, author, strlen(author), 1, 0, 1)) + if (!lowdown_html_esc(ob, author, strlen(author), 1, 0, 1)) return 0; if (!HBUF_PUTSL(ob, "</meta:initial-creator>\n")) return 0; @@ -998,13 +998,13 @@ if (date != NULL) { if (!HBUF_PUTSL(ob, "<dc:date>")) return 0; - if (!hesc_html(ob, date, strlen(date), 1, 0, 1)) + if (!lowdown_html_esc(ob, date, strlen(date), 1, 0, 1)) return 0; if (!HBUF_PUTSL(ob, "</dc:date>\n")) return 0; if (!HBUF_PUTSL(ob, "<meta:creation-date>")) return 0; - if (!hesc_html(ob, date, strlen(date), 1, 0, 1)) + if (!lowdown_html_esc(ob, date, strlen(date), 1, 0, 1)) return 0; if (!HBUF_PUTSL(ob, "</meta:creation-date>\n")) return 0; @@ -1022,7 +1022,7 @@ size_t length, const struct odt *st) { - return hesc_html(ob, source, length, 1, 0, 1); + return lowdown_html_esc(ob, source, length, 1, 0, 1); } /* @@ -1044,14 +1044,14 @@ const struct odt *st) { - return hesc_href(ob, in->data, in->size); + return lowdown_html_esc_href(ob, in->data, in->size); } static int escape_attr(struct lowdown_buf *ob, const struct lowdown_buf *in) { - return hesc_attr(ob, in->data, in->size); + return lowdown_html_esc_attr(ob, in->data, in->size); } /* @@ -1145,7 +1145,7 @@ if (parm->text.data[i] == ' ' && i < parm->text.size - 1 && parm->text.data[i + 1] == ' ') { - if (!hesc_html(ob, + if (!lowdown_html_esc(ob, &parm->text.data[j], sz, 1, 1, 1)) return 0; sz = 0; @@ -1162,7 +1162,7 @@ parm->text.data[i] == '\n') break; } - if (!hesc_html(ob, &parm->text.data[j], sz, 1, 1, 1)) + if (!lowdown_html_esc(ob, &parm->text.data[j], sz, 1, 1, 1)) return 0; if (!HBUF_PUTSL(ob, "</text:p>\n")) return 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/regress/diff/metadata-add.latex new/lowdown-1.3.1/regress/diff/metadata-add.latex --- old/lowdown-1.3.0/regress/diff/metadata-add.latex 2024-12-01 08:26:15.000000000 +0100 +++ new/lowdown-1.3.1/regress/diff/metadata-add.latex 2024-12-06 04:08:10.000000000 +0100 @@ -23,7 +23,6 @@ \title{} \author{kristaps} \maketitle - \hypertarget{section}{% \section{section}\label{section}} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/regress/diff/metadata-change.latex new/lowdown-1.3.1/regress/diff/metadata-change.latex --- old/lowdown-1.3.0/regress/diff/metadata-change.latex 2024-12-01 08:26:15.000000000 +0100 +++ new/lowdown-1.3.1/regress/diff/metadata-change.latex 2024-12-06 04:08:10.000000000 +0100 @@ -23,7 +23,6 @@ \title{} \author{shmistaps} \maketitle - \hypertarget{section}{% \section{section}\label{section}} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/regress/diff/metadata-remove.latex new/lowdown-1.3.1/regress/diff/metadata-remove.latex --- old/lowdown-1.3.0/regress/diff/metadata-remove.latex 2024-12-01 08:26:15.000000000 +0100 +++ new/lowdown-1.3.1/regress/diff/metadata-remove.latex 2024-12-06 04:08:10.000000000 +0100 @@ -20,7 +20,6 @@ \usepackage{longtable} \usepackage{hyperref} \begin{document} - \hypertarget{section}{% \section{section}\label{section}} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/regress/template/and-mismatch.xml new/lowdown-1.3.1/regress/template/and-mismatch.xml --- old/lowdown-1.3.0/regress/template/and-mismatch.xml 1970-01-01 01:00:00.000000000 +0100 +++ new/lowdown-1.3.1/regress/template/and-mismatch.xml 2024-12-06 04:08:10.000000000 +0100 @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <meta charset="utf-8" /> + <title>foo</title> + </head> + <body> + empty=[$ifdef(and(title,nope))$no$endif$] + empty=[$ifdef(and(title,))$no$endif$] + has=[$ifdef(and(title,authors))$yes$endif$] + has=[$ifdef(and(title))$yes$endif$] + empty=[$ifdef(and())$no$endif$] + empty=[$ifdef(and(,,))$no$endif$] + </body> +</html> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/regress/template/and-nested.html new/lowdown-1.3.1/regress/template/and-nested.html --- old/lowdown-1.3.0/regress/template/and-nested.html 1970-01-01 01:00:00.000000000 +0100 +++ new/lowdown-1.3.1/regress/template/and-nested.html 2024-12-06 04:08:10.000000000 +0100 @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <meta charset="utf-8" /> + <title>foo</title> + </head> + <body> + [ YES ] + empty=[] + [ YES ] + [ YES ] + empty=[] + </body> +</html> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/regress/template/and-nested.xml new/lowdown-1.3.1/regress/template/and-nested.xml --- old/lowdown-1.3.0/regress/template/and-nested.xml 1970-01-01 01:00:00.000000000 +0100 +++ new/lowdown-1.3.1/regress/template/and-nested.xml 2024-12-06 04:08:10.000000000 +0100 @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <meta charset="utf-8" /> + <title>foo</title> + </head> + <body> + [$ifdef(and(and(title,authors)))$ YES $endif$] + empty=[$ifdef(and(and(title,authors), and(title,)))$ NO $endif$] + [$ifdef(and(and(and(title))))$ YES $endif$] + [$ifdef(and(and(and(title),and(authors))))$ YES $endif$] + empty=[$ifdef(and(and(and(title,),and(authors))))$ YES $endif$] + </body> +</html> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/regress/template/and-or.html new/lowdown-1.3.1/regress/template/and-or.html --- old/lowdown-1.3.0/regress/template/and-or.html 1970-01-01 01:00:00.000000000 +0100 +++ new/lowdown-1.3.1/regress/template/and-or.html 2024-12-06 04:08:10.000000000 +0100 @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <meta charset="utf-8" /> + <title>foo</title> + </head> + <body> + has=[yes] + empty=[] + </body> +</html> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/regress/template/and-or.xml new/lowdown-1.3.1/regress/template/and-or.xml --- old/lowdown-1.3.0/regress/template/and-or.xml 1970-01-01 01:00:00.000000000 +0100 +++ new/lowdown-1.3.1/regress/template/and-or.xml 2024-12-06 04:08:10.000000000 +0100 @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <meta charset="utf-8" /> + <title>foo</title> + </head> + <body> + has=[$ifdef(and(title,or(authors,nope)))$yes$endif$] + empty=[$ifdef(and(title,or(authors,nope),no))$yes$endif$] + </body> +</html> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/regress/template/and.html new/lowdown-1.3.1/regress/template/and.html --- old/lowdown-1.3.0/regress/template/and.html 1970-01-01 01:00:00.000000000 +0100 +++ new/lowdown-1.3.1/regress/template/and.html 2024-12-06 04:08:10.000000000 +0100 @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <meta charset="utf-8" /> + <title>foo</title> + </head> + <body> + empty=[] + empty=[] + has=[yes] + has=[yes] + empty=[] + empty=[] + </body> +</html> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/regress/template/and.xml new/lowdown-1.3.1/regress/template/and.xml --- old/lowdown-1.3.0/regress/template/and.xml 1970-01-01 01:00:00.000000000 +0100 +++ new/lowdown-1.3.1/regress/template/and.xml 2024-12-06 04:08:10.000000000 +0100 @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <meta charset="utf-8" /> + <title>foo</title> + </head> + <body> + empty=[$ifdef(and(title,nope))$no$endif$] + empty=[$ifdef(and(title,))$no$endif$] + has=[$ifdef(and(title,authors))$yes$endif$] + has=[$ifdef(and(title))$yes$endif$] + empty=[$ifdef(and())$no$endif$] + empty=[$ifdef(and(,,))$no$endif$] + </body> +</html> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/regress/template/or-nested.html new/lowdown-1.3.1/regress/template/or-nested.html --- old/lowdown-1.3.0/regress/template/or-nested.html 1970-01-01 01:00:00.000000000 +0100 +++ new/lowdown-1.3.1/regress/template/or-nested.html 2024-12-06 04:08:10.000000000 +0100 @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <meta charset="utf-8" /> + <title>foo</title> + </head> + <body> + [ YES ] + [ YES ] + [ YES ] + [] + </body> +</html> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/regress/template/or-nested.xml new/lowdown-1.3.1/regress/template/or-nested.xml --- old/lowdown-1.3.0/regress/template/or-nested.xml 1970-01-01 01:00:00.000000000 +0100 +++ new/lowdown-1.3.1/regress/template/or-nested.xml 2024-12-06 04:08:10.000000000 +0100 @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <meta charset="utf-8" /> + <title>foo</title> + </head> + <body> + [$ifdef(or(or(title,authors)))$ YES $endif$] + [$ifdef(or(or(title,authors),))$ YES $endif$] + [$ifdef(or(or(no,alsono),title))$ YES $endif$] + [$ifdef(or(or(no,alsono),asdfsadf))$ NO $endif$] + </body> +</html> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/regress/template/or.html new/lowdown-1.3.1/regress/template/or.html --- old/lowdown-1.3.0/regress/template/or.html 1970-01-01 01:00:00.000000000 +0100 +++ new/lowdown-1.3.1/regress/template/or.html 2024-12-06 04:08:10.000000000 +0100 @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <meta charset="utf-8" /> + <title>foo</title> + </head> + <body> + empty=[] + has=[yes] + has=[yes] + has=[yes] + </body> +</html> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/regress/template/or.xml new/lowdown-1.3.1/regress/template/or.xml --- old/lowdown-1.3.0/regress/template/or.xml 1970-01-01 01:00:00.000000000 +0100 +++ new/lowdown-1.3.1/regress/template/or.xml 2024-12-06 04:08:10.000000000 +0100 @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <meta charset="utf-8" /> + <title>foo</title> + </head> + <body> + empty=[$ifdef(or(alsonope,nope))$no$endif$] + has=[$ifdef(or(alsonope,nope,authors))$yes$endif$] + has=[$ifdef(or(,,,,authors))$yes$endif$] + has=[$ifdef(or(title,asdf,fdsa))$yes$endif$] + </body> +</html> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/share/latex/default.latex new/lowdown-1.3.1/share/latex/default.latex --- old/lowdown-1.3.0/share/latex/default.latex 1970-01-01 01:00:00.000000000 +0100 +++ new/lowdown-1.3.1/share/latex/default.latex 2024-12-06 04:08:10.000000000 +0100 @@ -0,0 +1,31 @@ +% Options for packages loaded elsewhere +\PassOptionsToPackage{unicode}{hyperref} +\PassOptionsToPackage{hyphens}{url} +% +\documentclass[11pt,a4paper]{article} +\usepackage{amsmath,amssymb} +\usepackage{lmodern} +\usepackage{iftex} +\ifPDFTeX + \usepackage[T1]{fontenc} + \usepackage[utf8]{inputenc} + \usepackage{textcomp} % provide euro and other symbols +\else % if luatex or xetex + \usepackage{unicode-math} + \defaultfontfeatures{Scale=MatchLowercase} + \defaultfontfeatures[\\rmfamily]{Ligatures=TeX,Scale=1} +\fi +\usepackage{xcolor} +\usepackage{graphicx} +\usepackage{longtable} +\usepackage{hyperref} +$latexheader$ +\begin{document} +$ifdef(or(title,author,date))$\title{$title.escapelatex$}$endif$ +$ifdef(author)$ +\author{$author.escapelatex$$ifdef(affiliation)$ \\ $affiliation.escapelatex$$endif$} +$endif$ +$ifdef(date)$\date{$date.escapelatex$}$endif$ +$ifdef(or(title,author,date))$\maketitle$endif$ +$body$ +\end{document} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/template.c new/lowdown-1.3.1/template.c --- old/lowdown-1.3.0/template.c 2024-12-01 08:26:15.000000000 +0100 +++ new/lowdown-1.3.1/template.c 2024-12-06 04:08:10.000000000 +0100 @@ -102,6 +102,9 @@ static int op_exec(const struct op *, struct lowdown_buf *, const struct lowdown_metaq *, const struct lowdown_buf *, const char *); +static struct op_resq *op_eval(const char *, size_t, + const struct lowdown_metaq *, const char *, const struct op_resq *, + const struct lowdown_buf *); /* * Allocate the generic members of "struct op". The caller should be @@ -426,7 +429,7 @@ TAILQ_FOREACH(res, input, entries) { hbuf_truncate(buf); - if (!hesc_href(buf, res->res, strlen(res->res))) + if (!lowdown_html_esc_href(buf, res->res, strlen(res->res))) goto err; if ((nres = calloc(1, sizeof(struct op_res))) == NULL) goto err; @@ -464,7 +467,45 @@ TAILQ_FOREACH(res, input, entries) { hbuf_truncate(buf); - if (!hesc_attr(buf, res->res, strlen(res->res))) + if (!lowdown_html_esc_attr(buf, res->res, strlen(res->res))) + goto err; + if ((nres = calloc(1, sizeof(struct op_res))) == NULL) + goto err; + TAILQ_INSERT_TAIL(nq, nres, entries); + nres->res = strndup(buf->data, buf->size); + if (nres->res == NULL) + goto err; + } + hbuf_free(buf); + return nq; +err: + hbuf_free(buf); + op_resq_free(nq); + return NULL; +} + +/* + * LaTeX-escape (for general content) all characters in all list items. + * Returns NULL on allocation failure. + */ +static struct op_resq * +op_eval_function_escape_latex(const struct lowdown_metaq *mq, + const struct op_resq *input) +{ + struct op_resq *nq = NULL; + struct op_res *nres; + const struct op_res *res; + struct lowdown_buf *buf; + + if ((buf = hbuf_new(32)) == NULL) + goto err; + if ((nq = malloc(sizeof(struct op_resq))) == NULL) + goto err; + TAILQ_INIT(nq); + + TAILQ_FOREACH(res, input, entries) { + hbuf_truncate(buf); + if (!lowdown_latex_esc(buf, res->res, strlen(res->res))) goto err; if ((nres = calloc(1, sizeof(struct op_res))) == NULL) goto err; @@ -502,7 +543,7 @@ TAILQ_FOREACH(res, input, entries) { hbuf_truncate(buf); - if (!hesc_html(buf, res->res, strlen(res->res), + if (!lowdown_html_esc(buf, res->res, strlen(res->res), 1, 0, 0)) goto err; if ((nres = calloc(1, sizeof(struct op_res))) == NULL) @@ -629,6 +670,8 @@ nq = op_eval_function_join(mq, input); else if (exprsz == 4 && strncasecmp(expr, "trim", 4) == 0) nq = op_resq_clone(input, 1); + else if (exprsz == 11 && strncasecmp(expr, "escapelatex", 11) == 0) + nq = op_eval_function_escape_latex(mq, input); else if (exprsz == 10 && strncasecmp(expr, "escapehtml", 10) == 0) nq = op_eval_function_escape_html(mq, input); else if (exprsz == 14 && strncasecmp(expr, "escapehtmlattr", 14) == 0) @@ -652,11 +695,12 @@ size_t argsz, const char *this, const struct lowdown_metaq *mq, const struct lowdown_buf *content) { - struct op_resq *q; + struct op_resq *q, *resq; struct op_res *res; const struct lowdown_meta *m; const char *v = NULL; - size_t vsz; + size_t i, vsz, stack = 0, start; + int rc; if ((q = malloc(sizeof(struct op_resq))) == NULL) return NULL; @@ -671,6 +715,103 @@ /* Body of HTML document. */ v = content->data; vsz = content->size; + } else if (exprsz == 2 && strncasecmp(expr, "or", exprsz) == 0) { + /* "OR" of all arguments. */ + for (rc = 0, start = i = 0; rc == 0 && i < argsz; i++) { + /* + * Read until next comma, then evaluate its + * arguments. Short-circuit if arguments + * evaluate to true. Check stack to pass over + * sub-arguments. + */ + + if (args[i] == '(') { + stack++; + continue; + } else if (args[i] == ')') { + stack--; + continue; + } else if (args[i] != ',' || stack > 0) + continue; + + /* Evaluate or empty evaluates to false. */ + + if (i > start) { + resq = op_eval(&args[start], i - start, + mq, this, NULL, content); + if (resq == NULL) + return 0; + rc = !TAILQ_EMPTY(resq); + op_resq_free(resq); + } else + rc = 0; + start = i + 1; + } + + /* Catch remaining arguments. */ + + if (i > start && rc == 0) { + resq = op_eval(&args[start], i - start, mq, + this, NULL, content); + if (resq == NULL) + return 0; + rc = !TAILQ_EMPTY(resq); + op_resq_free(resq); + } + + if (rc == 1) { + v = "true"; + vsz = 4; + } + } else if (exprsz == 3 && strncasecmp(expr, "and", exprsz) == 0) { + /* "And" of all arguments. */ + for (rc = 1, start = i = 0; rc == 1 && i < argsz; i++) { + /* + * Read until next comma, then evaluate its + * arguments. Short-circuit if arguments + * evaluate to false. Check stack to pass over + * sub-arguments. + */ + + if (args[i] == '(') { + stack++; + continue; + } else if (args[i] == ')') { + stack--; + continue; + } else if (args[i] != ',' || stack > 0) + continue; + + /* Evaluate or empty evaluates to false. */ + + if (i > start) { + resq = op_eval(&args[start], i - start, + mq, this, NULL, content); + if (resq == NULL) + return 0; + rc = !TAILQ_EMPTY(resq); + op_resq_free(resq); + } else + rc = 0; + start = i + 1; + } + + /* Catch remaining arguments. */ + + if (i > start && rc == 1) { + resq = op_eval(&args[start], i - start, mq, + this, NULL, content); + if (resq == NULL) + return 0; + rc = !TAILQ_EMPTY(resq); + op_resq_free(resq); + } else if (i == start) + rc = 0; + + if (rc == 1) { + v = "true"; + vsz = 4; + } } else { /* * If "meta", interpret argument as being a metadata diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lowdown-1.3.0/versions.xml new/lowdown-1.3.1/versions.xml --- old/lowdown-1.3.0/versions.xml 2024-12-01 08:26:15.000000000 +0100 +++ new/lowdown-1.3.1/versions.xml 2024-12-06 04:08:10.000000000 +0100 @@ -1643,4 +1643,21 @@ </p> </aside> </article> + <article data-sblg-article="1" data-sblg-tags="version"> + <header> + <h1>1.3.1</h1> + <address>Kristaps Dzonsons</address> + <time datetime="2024-12-05">2024-12-05</time> + </header> + <aside> + <p> + Add <b>--template</b> functionality to <b>-tlatex</b>. + </p> + <p> + Add <code>and()</code> and <code>or()</code> as initial + values to template expressions. These allow for + <code>ifdef</code> to test for multiple values at once. + </p> + </aside> + </article> </articles> ++++++ lowdown.obsinfo ++++++ --- /var/tmp/diff_new_pack.HBy9N9/_old 2024-12-08 11:38:19.064581076 +0100 +++ /var/tmp/diff_new_pack.HBy9N9/_new 2024-12-08 11:38:19.068581243 +0100 @@ -1,5 +1,5 @@ name: lowdown -version: 1.3.0 -mtime: 1733037975 -commit: 7f0c33949a20c7fbdad3a8f479ca28c17b5f7b25 +version: 1.3.1 +mtime: 1733454490 +commit: 6c42fe9655f5db3a0d7eb1ccaa3c1830f211481a