aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremias Stotter <jeremias@stotter.eu>2022-03-20 20:14:18 +0100
committerJeremias Stotter <jeremias@stotter.eu>2022-03-20 20:14:18 +0100
commit1485eeeae32c9bf7c2bae956e9068c905b9a73d9 (patch)
tree13d455a055f76c07183e495dfc4268e3ec9d7216
parent76082c1cbbba512f68d157e441e8d1941823a128 (diff)
downloadJBlog-1485eeeae32c9bf7c2bae956e9068c905b9a73d9.tar.gz
JBlog-1485eeeae32c9bf7c2bae956e9068c905b9a73d9.tar.bz2
JBlog-1485eeeae32c9bf7c2bae956e9068c905b9a73d9.zip
Added ordered lists
-rw-r--r--md.c108
1 files changed, 81 insertions, 27 deletions
diff --git a/md.c b/md.c
index a1db73d..33b6b4e 100644
--- a/md.c
+++ b/md.c
@@ -36,6 +36,15 @@
char* get_link_components(char* start, char** out_text, char** out_loc, size_t* out_len);
+struct list_data {
+ // True if ol, false if ul
+ bool ordered;
+ // If ol this is set to the number the list starts counting from, in case of ul it is ignored
+ int start;
+ // The number of spaces used at this level of the list
+ int indent;
+};
+
enum html_type {
t_root = 0,
t_inner,
@@ -47,7 +56,7 @@ enum html_type {
t_img,
t_a,
t_ol,
- t_ul, // Value contains the ammount of spaces used to indent at that level
+ t_list, // Value contains the ammount of spaces used to indent at that level
t_li,
t_hr,
t_code,
@@ -155,8 +164,8 @@ char* realloc_append(char* dest, char* src) {
#define emb_html "<em><b>%s</b></em>\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 ol_html "<ol start=\"%d\">%s</ol>\n"
#define li_html "<li>%s</li>\n"
#define hr_html "<hr/>\n"
#define code_html "<pre><code>%s</code></pre>\n"
@@ -231,9 +240,18 @@ char* tree_to_html(struct tree_element* root) {
html = realloc_for_html(br_html);
strcpy(html, br_html);
break;
- case(t_ul):
- html = realloc_for_html(ul_html);
- sprintf(html, ul_html, inner_html ? inner_html : "");
+ case(t_list):
+ if(((struct list_data*)(root->value))->ordered) {
+ // We have an ordered list
+ int digits = 0;
+ for(int counter = 1; counter < ((struct list_data*)(root->value))->start; counter *= 10, digits++);
+ html = realloc(html, realloc_len(ol_html) + digits + 1);
+ sprintf(html, ol_html, ((struct list_data*)(root->value))->start, inner_html ? inner_html : "");
+ } else {
+ // We have an unordered list
+ html = realloc_for_html(ul_html);
+ sprintf(html, ul_html, inner_html ? inner_html : "");
+ }
break;
case(t_li):
html = realloc_for_html(li_html);
@@ -306,12 +324,15 @@ void append_char_to_active(struct tree_element* root, struct tree_element** acti
// This adds a new unordered list and returns a pointer to it
// indent is the spaces that the list indicator ( * or - ) was intendend
-struct tree_element* new_ul(struct tree_element* parent, int indent) {
- struct tree_element *new_ul;
- NEW_ACTIVE_CHILD(new_ul, parent, -1, t_ul, false);
- new_ul->value = malloc(sizeof(int));
- *(int*)new_ul->value = indent;
- return new_ul;
+struct tree_element* new_list(struct tree_element* parent, int indent, bool ordered, int start) {
+ struct tree_element *new_list;
+ NEW_ACTIVE_CHILD(new_list, parent, -1, t_list, false);
+ struct list_data* data = malloc(sizeof(struct list_data));
+ data->indent = indent;
+ data->ordered = ordered;
+ data->start = start;
+ new_list->value = data;
+ return new_list;
}
// Walk up the tree until root, stop if we encounter the requested type and return that node, otherwise return NULL
@@ -422,6 +443,8 @@ int parse_markdown(char* input, char* buffer, size_t buffer_size) {
bool escaped = false;
bool newline = false;
bool list_waiting = false;
+ bool ol_list = false;
+ int ol_start = 0;
// This will be set to some non-null value when there is a code element to return to
struct tree_element* code_element = NULL;
@@ -595,6 +618,26 @@ int parse_markdown(char* input, char* buffer, size_t buffer_size) {
spaces_trimmed = 0;
soft_newline_count = 0;
break;
+ // Numbered lists
+ case('1'):
+ case('2'):
+ case('3'):
+ case('4'):
+ case('5'):
+ case('6'):
+ case('7'):
+ case('8'):
+ case('9'):
+ case('0'):
+ if((active_element == root || newline) && *(cur_char+1) == '.' && *(cur_char+2) == ' ') {
+ list_waiting = true;
+ ol_list = true;
+ ol_start = 0;
+ sscanf(cur_char, "%d.", &ol_start);
+ cur_char++;
+ } else
+ goto default2;
+ break;
case('*'):
if((active_element == root || newline) && *(cur_char+1) == ' ' ) {
list_waiting = true;
@@ -728,33 +771,43 @@ int parse_markdown(char* input, char* buffer, size_t buffer_size) {
* 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 = find_parent_type(root, active_element, t_ul);;
- bool found_ul = false;
+ struct tree_element* look_element = find_parent_type(root, active_element, t_list);;
+ bool found_list = false;
while(look_element != NULL){
- // Enter new child ul
- if(*(int*)look_element->value < spaces_trimmed) {
- active_element = new_ul(look_element, spaces_trimmed);
- found_ul = true;
+ // Out list has more indents and is therefore a child to the one we found
+ // Enter new child list
+ if(((struct list_data*)look_element->value)->indent < spaces_trimmed) {
+ active_element = new_list(look_element, spaces_trimmed, ol_list, ol_start);
+ found_list = true;
break;
- }
+ }
// We found a list of the exact indentation level
- if(*(int*)look_element->value == spaces_trimmed) {
- active_element = look_element;
- found_ul = true;
+ else if(((struct list_data*)look_element->value)->indent == spaces_trimmed) {
+ // If the list type is the same simply mark the found element as active, otherwise create a new sibling list
+ if(((struct list_data*)look_element->value)->ordered == ol_list) {
+ active_element = look_element;
+ found_list = true;
+ } else {
+ active_element = new_list(look_element->parent, spaces_trimmed, ol_list, ol_start);
+ found_list = true;
+ break;
+ }
break;
- }
- if(*(int*)look_element->value > spaces_trimmed)
- look_element = find_parent_type(root, look_element->parent, t_ul);
+ }
+ // The current list has fewer indents than what we found, look farther for a parent
+ else if(((struct list_data*)look_element->value)->indent > spaces_trimmed)
+ look_element = find_parent_type(root, look_element->parent, t_list);
else
- look_element = find_parent_type(root, look_element, t_ul);
+ look_element = find_parent_type(root, look_element, t_list);
}
// Enter a new list
- if(!found_ul) {
- active_element = new_ul(root, spaces_trimmed);
+ if(!found_list) {
+ active_element = new_list(root, spaces_trimmed, ol_list, ol_start);
}
NEW_ACTIVE_CHILD(active_element, active_element, -1, t_li, true);
root_on_newline = true;
list_waiting = false;
+ ol_list = false;
}
// Trim spaces from newline
if(active_element == root || newline) {
@@ -770,6 +823,7 @@ int parse_markdown(char* input, char* buffer, size_t buffer_size) {
DEFAULT_CHECKS;
newline = false;
list_waiting = false;
+ ol_list = false;
append_char_to_active(root, &active_element, *cur_char);
break;
}
Jeremias Stotters git repositories generated by CGIT