aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremias Stotter <jeremias@stotter.eu>2021-12-19 23:02:50 +0100
committerJeremias Stotter <jeremias@stotter.eu>2021-12-19 23:02:50 +0100
commit0c334adfc7999b394c7f30de637d9a82a6e6b2ca (patch)
tree878f151f4c66757cae2b0e3a4e28c4e49e4c9070
parentdfe97a5b05299d98a1b29c4c970e57b8b98f3996 (diff)
downloadJBlog-0c334adfc7999b394c7f30de637d9a82a6e6b2ca.tar.gz
JBlog-0c334adfc7999b394c7f30de637d9a82a6e6b2ca.tar.bz2
JBlog-0c334adfc7999b394c7f30de637d9a82a6e6b2ca.zip
Unordered lists work now
The tree aproach really helps for things like this (;
-rw-r--r--md.c153
1 files changed, 115 insertions, 38 deletions
diff --git a/md.c b/md.c
index 5cb0340..09a324a 100644
--- a/md.c
+++ b/md.c
@@ -46,7 +46,7 @@ enum html_type {
t_img,
t_a,
t_ol,
- t_ul,
+ t_ul, // Value contains the ammount of spaces used to indent at that level
t_li
};
@@ -78,12 +78,27 @@ void free_tree(struct tree_element* root) {
free(root);
}
-struct tree_element* new_child(struct tree_element* parent) {
+// Index may be -1, then we will add to the end
+// Otherwise we add at location index
+//
+// Index may only be between -1 and parent->children_n + 1, otherwise this will crash
+struct tree_element* new_child(struct tree_element* parent, int index) {
parent->children_n++;
parent->children = realloc(parent->children, sizeof(struct tree_element*)*(parent->children_n));
struct tree_element* child = new_element();
child->parent = parent;
- (parent->children)[parent->children_n-1] = child;
+ if(index == -1)
+ (parent->children)[parent->children_n-1] = child;
+ else {
+ // Move the elements in the children list after the new element
+ for(int i = 0; i < (parent->children_n - index - 1); i++) {
+ /*memmove(parent->children + (parent->children_n - i - 1) * sizeof(struct tree_element*),
+ parent->children + (parent->children_n - i - 2) * sizeof(struct tree_element*),
+ sizeof(struct tree_element*));*/
+ (parent->children)[parent->children_n - i - 1] = (parent->children)[parent->children_n - i - 2];
+ }
+ (parent->children)[index] = child;
+ }
return child;
}
@@ -134,22 +149,30 @@ char* tree_to_html(struct tree_element* root) {
case(t_p):
html = realloc_for_html(p_html);
sprintf(html, p_html, inner_html ? inner_html : "");
- break;
+ 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;
+ break;
case(t_str):
html = realloc_for_html(em_html);
sprintf(html, em_html, inner_html ? inner_html : "");
- break;
+ break;
case(t_br):
html = realloc_for_html(b_html);
strcpy(html, br_html);
- break;
+ break;
+ case(t_ul):
+ html = realloc_for_html(ul_html);
+ sprintf(html, ul_html, inner_html ? inner_html : "");
+ break;
+ case(t_li):
+ html = realloc_for_html(li_html);
+ sprintf(html, li_html, inner_html ? inner_html : "");
+ break;
default:
html=inner_html;
- break;
+ break;
}
return html;
}
@@ -159,12 +182,12 @@ void append_char_to_active(struct tree_element* root, struct tree_element** acti
// 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 = new_child(root, -1);
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 = new_child(new_active_element, -1);
new_active_element->type = t_inner;
}
if((cur_char <= 47 ||
@@ -191,16 +214,18 @@ int parse_markdown(char* input, char* buffer, size_t buffer_size) {
bool newline = true;
int hash_chain = 0;
+ int spaces_trimmed = 0;
struct tree_element* root = new_element();
struct tree_element* active_element = root;
for(char* cur_char = input; *cur_char != '\0'; cur_char++) {
+ printf("%c", *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);
+ struct tree_element* br_child = new_child(active_element, -1);
br_child->type = t_br;
} else {
append_char_to_active(root, &active_element, *cur_char);
@@ -208,33 +233,19 @@ int parse_markdown(char* input, char* buffer, size_t buffer_size) {
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) {
// Character escaping
case('\\'):
escaped = true;
- break;
+ break;
// Tabs
case('\t'):
- break;
+ break;
// Newline
case('\r'):
// Ignoring \r goes against the commonmark spec, but who cares
- break;
+ break;
case('\n'):
if(hash_chain > 0)
active_element = root;
@@ -246,31 +257,73 @@ int parse_markdown(char* input, char* buffer, size_t buffer_size) {
newline = true;
}
hash_chain = 0;
- break;
+ spaces_trimmed = 0;
+ break;
// Text strength
case('*'):
-
- break;
+ void new_ul(struct tree_element* parent) {
+ active_element = new_child(parent, -1);
+ active_element->type = t_ul;
+ active_element->allow_inner = false;
+ active_element->value = malloc(sizeof(int));
+ printf("SPACES TRIMMED: %d\n", spaces_trimmed);
+ *(int*)active_element->value = spaces_trimmed;
+ }
+ if(active_element == root || newline) {
+ newline = false;
+ // Look if we have an ancestor somewhere that has spaces fewer or equal to the spaces we skipped.
+ // On fewer spaces we enter a new list below the one we found
+ // Is it equal we just add a new list item
+ // If we do not find a list we create a new one at the root node
+ struct tree_element* look_element = active_element;
+ bool found_ul = false;
+ while(look_element && look_element != root){
+ if(look_element->type == t_ul) {
+ if(*(int*)look_element->value < spaces_trimmed) {
+ new_ul(look_element);
+ found_ul = true;
+ break;
+ }
+ if(*(int*)look_element->value == spaces_trimmed) {
+ active_element = look_element;
+ found_ul = true;
+ break;
+ }
+ }
+ look_element = look_element->parent;
+ }
+ // Enter a new list
+ if(!found_ul) {
+ new_ul(root);
+ }
+
+ active_element = new_child(active_element, -1);
+ active_element->type = t_li;
+ active_element->allow_inner = true;
+ } else {
+ }
+ break;
case('_'):
- break;
+ break;
case('`'):
- break;
+ break;
case('~'):
- break;
+ break;
// Titles
case('='):
if(newline) {
// Make the last line a title, otherwise we fall through
break;
}
+ break;
case('-'):
if(newline) {
// Make the last line a title, otherwise we fall through
break;
}
+ break;
case('#'):
- printf("%s\n", newline ? "a" : "b");
if(hash_chain == 0 || newline) {
if(active_element == root || newline) {
active_element = root;
@@ -283,23 +336,47 @@ int parse_markdown(char* input, char* buffer, size_t buffer_size) {
break;
}
case(' '):
+ 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, -1);
+ active_element->allow_inner = true;
+ active_element->type = t_h;
+ active_element->value = malloc(sizeof(int));
+ }
+ }
+ *(int*)(active_element->value) = hash_chain;
+ hash_chain = 0;
+ break;
+ }
// Trim spaces from newline
if(active_element == root || newline) {
+ //@todo with this we should relatively easily be able to check for code blocks!
+ spaces_trimmed++;
break;
}
// Default character handling
default:
- hash_chain = 0;
+ if(hash_chain > 0) {
+ for(int i = 0; i < hash_chain; i++)
+ append_char_to_active(root, &active_element, '#');
+ hash_chain = 0;
+ }
newline = false;
append_char_to_active(root, &active_element, *cur_char);
break;
}
}
+ // Convert the tree to valid html
char* html = tree_to_html(root);
- printf("%s\n", html ? html : "" );
+ //printf("%s\n", html ? html : "" );
// Tear down the tree
free_tree(root);
- strncpy(buffer, html, buffer_size - 1);
+ if(html) {
+ 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