feat(ast): wrote initial ast-to-html function

main
Jef Roosens 2024-03-16 13:55:44 +01:00
parent 5c96031834
commit 8a758d3824
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
3 changed files with 73 additions and 2 deletions

View File

@ -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

68
src/ast/html.c 100644
View File

@ -0,0 +1,68 @@
#include <stdio.h>
#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, "<h%lu>", child->d.header.depth);
MRK_RES(mrk_buf_append_n(buf, tag, 4));
MRK_RES(__mrk_ast_to_html(buf, orig, child));
sprintf(tag, "</h%lu>", 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;
// <a href="[url]">
char tag[12 + url_len];
sprintf(tag, "<a href=\"%.*s\">", (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, "</a>", 4));
} break;
case mrk_ast_node_type_paragraph:
MRK_RES(mrk_buf_append_n(buf, "<p>", 3));
MRK_RES(__mrk_ast_to_html(buf, orig, child));
MRK_RES(mrk_buf_append_n(buf, "</p>", 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;
}