diff --git a/include/mrk/ast.h b/include/mrk/ast.h index 6d924cd..fc7f090 100644 --- a/include/mrk/ast.h +++ b/include/mrk/ast.h @@ -6,8 +6,6 @@ #include "mrk/common.h" -#define MRK_AST_NODE_ARGS 4 - typedef enum mrk_ast_node_type { mrk_ast_node_type_none = 0, mrk_ast_node_type_header, @@ -48,4 +46,9 @@ mrk_err mrk_ast_node_init(mrk_ast_node **out); */ mrk_err mrk_ast_node_child_append(mrk_ast_node **out, mrk_ast_node *parent); +/** + * Output the AST as valid HTML + */ +mrk_err mrk_ast_to_html(char **out, const char *orig, mrk_ast_node *root); + #endif diff --git a/src/ast.c b/src/ast/ast.c similarity index 100% rename from src/ast.c rename to src/ast/ast.c diff --git a/src/ast/html.c b/src/ast/html.c new file mode 100644 index 0000000..e3a66f4 --- /dev/null +++ b/src/ast/html.c @@ -0,0 +1,68 @@ +#include + +#include "mrk/ast.h" +#include "mrk/buf.h" + +mrk_err __mrk_ast_to_html(mrk_buf *buf, const char *orig, mrk_ast_node *root) { + + for (size_t i = 0; i < root->children.len; i++) { + mrk_ast_node *child = root->children.arr[i]; + + switch (child->type) { + case mrk_ast_node_type_text: + // TODO replace certain characters with escape sequences + MRK_RES(mrk_buf_append_n(buf, orig + child->d.text.start, + child->d.text.end - child->d.text.start)); + break; + case mrk_ast_node_type_header: { + char tag[6]; + + sprintf(tag, "", child->d.header.depth); + MRK_RES(mrk_buf_append_n(buf, tag, 4)); + + MRK_RES(__mrk_ast_to_html(buf, orig, child)); + + sprintf(tag, "", child->d.header.depth); + MRK_RES(mrk_buf_append_n(buf, tag, 5)); + } break; + case mrk_ast_node_type_space: + MRK_RES(mrk_buf_append_n(buf, " ", 1)); + break; + case mrk_ast_node_type_link: { + size_t url_len = child->d.link.url_end - child->d.link.url_start; + + // + char tag[12 + url_len]; + + sprintf(tag, "", (int)url_len, + orig + child->d.link.url_start); + MRK_RES(mrk_buf_append_n(buf, tag, 11 + url_len)); + + MRK_RES(__mrk_ast_to_html(buf, orig, child)); + + MRK_RES(mrk_buf_append_n(buf, "", 4)); + } break; + case mrk_ast_node_type_paragraph: + MRK_RES(mrk_buf_append_n(buf, "

", 3)); + MRK_RES(__mrk_ast_to_html(buf, orig, child)); + MRK_RES(mrk_buf_append_n(buf, "

", 4)); + break; + case mrk_ast_node_type_none: + break; + } + } + + return mrk_err_ok; +} + +mrk_err mrk_ast_to_html(char **out, const char *orig, mrk_ast_node *root) { + mrk_buf buf; + MRK_RES(mrk_buf_init(&buf)); + + MRK_RES(__mrk_ast_to_html(&buf, orig, root)); + MRK_RES(mrk_buf_compact(&buf)); + + *out = buf.s; + + return mrk_err_ok; +}