From aa2edcdf68676c3839593309af97b335cb8388b8 Mon Sep 17 00:00:00 2001 From: Linnnus Date: Sun, 4 Feb 2024 18:45:16 +0100 Subject: feat(creole): escape special HTML characters --- src/creole-test.c | 10 +++++----- src/creole.c | 32 +++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/creole-test.c b/src/creole-test.c index 835ee42..3020c51 100644 --- a/src/creole-test.c +++ b/src/creole-test.c @@ -10,6 +10,11 @@ struct { const char *name, *input, *output; } tests[] = { + { + .name = "Basic paragraph markup", + .input = "Basic paragraph test with <, >, & and \"", + .output = "

Basic paragraph test with <, >, & and "

" + }, { .name = "Two paragraphs next to each other.", .input = "Hello,\n\nworld!", @@ -51,11 +56,6 @@ struct { .output = "

======= Header =

" }, #if 0 - { - .name = "Basic paragraph markup", - .input = "Basic paragraph test with <, >, & and \"", - .output = "

Basic paragraph test with <, >, & and "

" - }, { .name = "Simple unordered list", .input = "* list item\n*list item 2", diff --git a/src/creole.c b/src/creole.c index b3d1a87..7472a3b 100644 --- a/src/creole.c +++ b/src/creole.c @@ -6,6 +6,7 @@ #include #include #include +#include #define LENGTH(x) (sizeof(x)/sizeof((x)[0])) @@ -14,6 +15,7 @@ void process(const char *begin, const char *end, bool new_block, FILE *out); int do_headers(const char *begin, const char *end, bool new_block, FILE *out); int do_paragraph(const char *begin, const char *end, bool new_block, FILE *out); +int do_replacements(const char *begin, const char *end, bool new_block, FILE *out); // A parser takes a (sub)string and returns the number of characters consumed, if any. // @@ -21,7 +23,7 @@ int do_paragraph(const char *begin, const char *end, bool new_block, FILE *out); // The sign of the return value determines whether a new block should begin, after the consumed text. typedef int (* parser_t)(const char *begin, const char *end, bool new_block, FILE *out); -static parser_t parsers[] = { do_headers, do_paragraph }; +static parser_t parsers[] = { do_headers, do_paragraph, do_replacements }; int do_headers(const char *begin, const char *end, bool new_block, FILE *out) { if (!new_block) { // Headers are block-level elements. @@ -87,6 +89,34 @@ found_double_newline: return -(stop - begin); } +static struct { + const char *from, *to; +} replacements[] = { + // Escaped special characters + // TODO (e.g. "\\{" should become "{" so users can escape and void it being parsed as markup + // Characters that have special meaning in HTML + {"<", "<"}, + {">", ">"}, + {"\"", """}, + {"&", "&"}, +}; + +int do_replacements(const char *begin, const char *end, bool new_block, FILE *out) +{ + for (unsigned i = 0; i < LENGTH(replacements); ++i) { + size_t length = strlen(replacements[i].from); + if (end - begin < length) { + continue; + } + if (strncmp(replacements[i].from, begin, length) == 0) { + fputs(replacements[i].to, out); + return length; + } + } + + return 0; +} + void process(const char *begin, const char *end, bool new_block, FILE *out) { const char *p = begin; while (p < end) { -- cgit v1.2.3