aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremias Stotter <jeremias@stotter.eu>2021-12-12 18:40:49 +0100
committerJeremias Stotter <jeremias@stotter.eu>2021-12-12 18:40:49 +0100
commitdfe97a5b05299d98a1b29c4c970e57b8b98f3996 (patch)
treefb1c81bc3a26ca40b09e646e45e06a41c2c1395f
parente96bc6ff7e1797cf633c909a964bd9d65c575ad1 (diff)
downloadJBlog-dfe97a5b05299d98a1b29c4c970e57b8b98f3996.tar.gz
JBlog-dfe97a5b05299d98a1b29c4c970e57b8b98f3996.tar.bz2
JBlog-dfe97a5b05299d98a1b29c4c970e57b8b98f3996.zip
A bit more of the new md parser works now
-rw-r--r--md.c197
1 files changed, 162 insertions, 35 deletions
diff --git a/md.c b/md.c
index 9587371..5cb0340 100644
--- a/md.c
+++ b/md.c
@@ -22,6 +22,8 @@
#include <stdlib.h>
#include <stdbool.h>
+#include <time.h>
+
#include "jblog.h"
#define LINE_MAX 4096
@@ -34,18 +36,13 @@ size_t append(char* in_dest, char* in_src);
size_t prepend(char* in_dest, char* in_src);
char* get_link_components(char* start, char** out_text, char** out_loc, size_t* out_len);
-enum html_types{
- inner,
- img,
-
-};
-
enum html_type {
t_root = 0,
t_inner,
+ t_h, // Contains a pointer to an int as its value, this pointer indicates title strength (1-6)
t_p,
- t_em,
- t_b,
+ t_br,
+ t_str, // t_str contains an int pointer as its level
t_img,
t_a,
t_ol,
@@ -59,6 +56,8 @@ struct tree_element {
int type;
int children_n;
struct tree_element** children;
+ // Is this element allowed to have inner html
+ bool allow_inner;
// Can be anythign additional, like src for img or text in the case of inner
void* value;
};
@@ -93,6 +92,7 @@ struct tree_element* new_child(struct tree_element* parent) {
// Reallocs the string dest to fit src, then append
char* realloc_append(char* dest, char* src) {
+ //printf("Dest:%sSrc:%s\n", dest ? dest : "", src ? src : "");
size_t dest_len = dest ? strlen(dest) : 0;
dest = realloc(dest, dest_len + (src ? strlen(src) : 0) + 1);
if(src)
@@ -100,81 +100,208 @@ char* realloc_append(char* dest, char* src) {
return dest;
}
-#define p_html "<p>%s</p>"
-#define em_html "<em>%s</p>"
-#define b_html "<b>%s</b>"
-#define img_html "<img src=\"%s\" alt=\"%s\" title=\"\"/>"
-#define a_html "<a href=%s>%s</a>"
-#define ol_html "<ol>%s</ol>"
-#define ul_html "<ul>%s</ul>"
-#define li_html "<li>%s</li>"
+#define p_html "<p>%s</p>\n"
+#define br_html "<br/>"
+#define h_html "<h%d>%s</h%d>\n"
+#define em_html "<em>%s</p>\n"
+#define b_html "<b>%s</b>\n"
+#define img_html "<img src=\"%s\" alt=\"%s\" title=\"\"/>\n"
+#define a_html "<a href=%s>%s</a>\n"
+#define ol_html "<ol>%s</ol>\n"
+#define ul_html "<ul>%s</ul>\n"
+#define li_html "<li>%s</li>\n"
// Resolve a tree to html
char* tree_to_html(struct tree_element* root) {
- char* html = NULL;
+ char* html=NULL;
+ char* inner_html = NULL;
for(int i = 0; i < root->children_n; i++) {
struct tree_element* child = root->children[i];
switch(child->type) {
case(t_inner):
// Append the inner html to buffer
- html = realloc_append(html, child->value);
+ inner_html = realloc_append(inner_html, child->value);
break;
- case(t_p):
+ default:
char* child_html = tree_to_html(child);
- html = realloc_append(html, child_html);
+ inner_html = realloc_append(inner_html, child_html);
free(child_html);
break;
}
}
+// printf("%s\n", inner_html ? inner_html : "(EMPTY)");
+ #define realloc_for_html(html_pattern) realloc(html, (inner_html ? strlen(inner_html) : 0) + strlen(html_pattern) + 1);
+ switch(root->type) {
+ case(t_p):
+ html = realloc_for_html(p_html);
+ sprintf(html, p_html, inner_html ? inner_html : "");
+ break;
+ case(t_h):
+ html = realloc_for_html(h_html);
+ sprintf(html, h_html, *(int*)(root->value), inner_html ? inner_html : "", *(int*)(root->value));
+ break;
+ case(t_str):
+ html = realloc_for_html(em_html);
+ sprintf(html, em_html, inner_html ? inner_html : "");
+ break;
+ case(t_br):
+ html = realloc_for_html(b_html);
+ strcpy(html, br_html);
+ break;
+ default:
+ html=inner_html;
+ break;
+ }
return html;
}
+// This appends the cur_char to active element / it creates a new active element if the active element can not have text
+void append_char_to_active(struct tree_element* root, struct tree_element** active_element, char cur_char) {
+ // We are not allowed to add inner to this element so we'll start a new paragraph
+ struct tree_element* new_active_element = *active_element;
+ if(!(new_active_element->allow_inner) && new_active_element->type != t_inner) {
+ new_active_element = new_child(root);
+ new_active_element->type = t_p;
+ new_active_element->allow_inner = true;
+ }
+ if(new_active_element->type != t_inner) {
+ new_active_element = new_child(new_active_element);
+ new_active_element->type = t_inner;
+ }
+ if((cur_char <= 47 ||
+ (cur_char >=58 && cur_char <=64) ||
+ (cur_char >=91 && cur_char <=96) ||
+ cur_char > 122) && cur_char != 0x20) {
+ // Escape just to be safe
+ char append[8] = "";
+ html_escape(append, cur_char);
+ new_active_element->value = realloc_append(new_active_element->value, append);
+ } else {
+ // This is stupid, improve this later xD
+ char append[2] = {cur_char, '\0'};
+ new_active_element->value = realloc_append(new_active_element->value, append);
+ }
+ *active_element = new_active_element;
+}
+
// The program needs to loop through the loop again to cose all the open things at the end, THIS NEEDS TO BE IMPLEMENTED for xhtml
int parse_markdown(char* input, char* buffer, size_t buffer_size) {
+ clock_t before = clock();
memset(buffer, 0, buffer_size);
bool escaped = false;
- bool newline = false;
+ bool newline = true;
+
+ int hash_chain = 0;
+
struct tree_element* root = new_element();
- struct tree_element* active_element = new_child(root);
+ struct tree_element* active_element = root;
for(char* cur_char = input; *cur_char != '\0'; cur_char++) {
if(escaped) {
escaped = false;
+ if(*cur_char == '\n' || *cur_char == '\r') {
+ if(active_element->parent)
+ active_element = active_element->parent;
+ struct tree_element* br_child = new_child(active_element);
+ br_child->type = t_br;
+ } else {
+ append_char_to_active(root, &active_element, *cur_char);
+ }
continue;
}
+
+ if(hash_chain > 0) {
+ if(active_element->type != t_h) {
+ if(active_element->parent ? active_element->parent->type == t_h : false) {
+ active_element = active_element->parent;
+ } else {
+ active_element = new_child(root);
+ active_element->allow_inner = true;
+ active_element->type = t_h;
+ active_element->value = malloc(sizeof(int));
+ }
+ }
+ *(int*)(active_element->value) = hash_chain;
+ }
+
switch(*cur_char) {
- case('\\'):
+ // Character escaping
+ case('\\'):
escaped = true;
break;
+ // Tabs
case('\t'):
break;
+ // Newline
case('\r'):
+ // Ignoring \r goes against the commonmark spec, but who cares
+ break;
case('\n'):
+ if(hash_chain > 0)
+ active_element = root;
if(newline) {
- // New active element
- active_element = new_child(active_element->parent);
+ // A double new line means we return the active element to root
+ active_element = root;
+ newline = false;
+ } else {
+ newline = true;
}
- newline = true;
+ hash_chain = 0;
break;
+ // Text strength
case('*'):
+
+ break;
case('_'):
-
+
break;
- default:
- /*
- if(!active_element->type) {
- active_element->type = t_inner;
+ case('`'):
+ break;
+ case('~'):
+ break;
+ // Titles
+ case('='):
+ if(newline) {
+ // Make the last line a title, otherwise we fall through
+ break;
+ }
+ case('-'):
+ if(newline) {
+ // Make the last line a title, otherwise we fall through
+ break;
}
- char append[2] = {*cur_char, '\0'};
- active_element->value = realloc_append(active_element->value, append);
- */
+ case('#'):
+ printf("%s\n", newline ? "a" : "b");
+ if(hash_chain == 0 || newline) {
+ if(active_element == root || newline) {
+ active_element = root;
+ hash_chain = 1;
+ newline = false;
+ break;
+ }
+ } else {
+ hash_chain++;
+ break;
+ }
+ case(' '):
+ // Trim spaces from newline
+ if(active_element == root || newline) {
+ break;
+ }
+ // Default character handling
+ default:
+ hash_chain = 0;
+ newline = false;
+ append_char_to_active(root, &active_element, *cur_char);
break;
}
}
char* html = tree_to_html(root);
- printf("%s\n", html);
+ printf("%s\n", html ? html : "" );
// Tear down the tree
free_tree(root);
+ strncpy(buffer, html, buffer_size - 1);
free(html);
+ printf("Time to process in ns: %ld\n", (clock() - before) / (CLOCKS_PER_SEC / 1000000));
return 0;
}
Jeremias Stotters git repositories generated by CGIT