diff options
Diffstat (limited to 'src/creole.c')
-rw-r--r-- | src/creole.c | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/src/creole.c b/src/creole.c index 56edbd8..2a16205 100644 --- a/src/creole.c +++ b/src/creole.c @@ -21,10 +21,15 @@ long do_raw_url(const char *begin, const char *end, bool new_block, FILE *out); long do_emphasis(const char *begin, const char *end, bool new_block, FILE *out); long do_bold(const char *begin, const char *end, bool new_block, FILE *out); long do_nowiki_inline(const char *begin, const char *end, bool new_block, FILE *out); +long do_nowiki_block(const char *begin, const char *end, bool new_block, FILE *out); -// Prints string escaped. +// Prints string with special HTML characters escaped. +// +// Unlike many other functions, this function does not assume that (end >= +// begin). This simplifies some logic in callers since bracket-matching is prone +// to off-by-one errors when the brackets are empty. void hprint(FILE *out, const char *begin, const char *end) { - for (const char *p = begin; p != end; p++) { + for (const char *p = begin; p < end; p++) { if (*p == '&') { fputs("&", out); } else if (*p == '"') { @@ -59,6 +64,7 @@ typedef long (* parser_t)(const char *begin, const char *end, bool new_block, FI static parser_t parsers[] = { // Block-level elements do_headers, + do_nowiki_block, do_paragraph, // <p> should be last as it eats anything // Inline-level elements @@ -356,7 +362,7 @@ long do_nowiki_inline(const char *begin, const char *end, bool new_block, FILE * trim_start += 1; } const char *trim_stop = stop; - while (isspace(trim_stop[-1])) { + while (isspace(trim_stop[-1]) && trim_start <= trim_stop - 1) { trim_stop -= 1; } @@ -367,7 +373,27 @@ long do_nowiki_inline(const char *begin, const char *end, bool new_block, FILE * return 3 + (stop - start) + 3; /* {{{...}}} */ } +long do_nowiki_block(const char *begin, const char *end, bool new_block, FILE *out) { + if (!(new_block && starts_with(begin, end, "{{{\n"))) { + return 0; + } + const char *start = begin + 4; + + const char *stop = strnstr(start - 1, "\n}}}", end - (start - 1)); + if (stop == NULL) { + return 0; + } + + fputs("<pre><code>", out); + hprint(out, start, stop); + fputs("</code></pre>", out); + + return -(stop - start + 8); +} + void process(const char *begin, const char *end, bool new_block, FILE *out) { + assert(begin <= end); + const char *p = begin; while (p < end) { // Eat all newlines if we're starting a block. |