summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinnnus <[email protected]>2024-02-04 18:45:16 +0100
committerLinnnus <[email protected]>2024-02-04 20:26:23 +0100
commitaa2edcdf68676c3839593309af97b335cb8388b8 (patch)
tree46aaa67c4fb671751691af1d18bf3c520dda4f6f
parent04ef019e858e6175c7b9e61bd00bab3d383890d7 (diff)
feat(creole): escape special HTML characters
-rw-r--r--src/creole-test.c10
-rw-r--r--src/creole.c32
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
@@ -11,6 +11,11 @@ struct {
const char *name, *input, *output;
} tests[] = {
{
+ .name = "Basic paragraph markup",
+ .input = "Basic paragraph test with <, >, & and \"",
+ .output = "<p>Basic paragraph test with &lt;, &gt;, &amp; and &quot;</p>"
+ },
+ {
.name = "Two paragraphs next to each other.",
.input = "Hello,\n\nworld!",
.output = "<p>Hello,</p><p>world!</p>"
@@ -52,11 +57,6 @@ struct {
},
#if 0
{
- .name = "Basic paragraph markup",
- .input = "Basic paragraph test with <, >, & and \"",
- .output = "<p>Basic paragraph test with &lt;, &gt;, &amp; and &quot;</p>"
- },
- {
.name = "Simple unordered list",
.input = "* list item\n*list item 2",
.output = "<ul><li> list item</li>\n<li>list item 2</li></ul>"
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 <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#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
+ {"<", "&lt;"},
+ {">", "&gt;"},
+ {"\"", "&quot;"},
+ {"&", "&amp;"},
+};
+
+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) {