]> uap-core.de Git - note.git/commitdiff
fix markdown syntax tree generation
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Fri, 14 Mar 2025 11:09:08 +0000 (12:09 +0100)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Fri, 14 Mar 2025 11:09:08 +0000 (12:09 +0100)
application/editor.c
application/tests/test-editor.c

index 93289afda437785cd15d17ca9b224e664d1c4fe1..c3694121f9d03a1e0e6b1a80c571e724b46871a1 100644 (file)
@@ -120,6 +120,7 @@ static void textstack_update_last_element(CxList *stack_list, MDNode *t) {
 
 static void md_node_add_child(MDNode *node, MDNode *child) {
     cx_linked_list_add((void**)&node->children_begin, (void**)&node->children_end, -1, offsetof(MDNode, next), child);
+    child->parent = node;
 }
 
 // create a node and add it to the current paragraph node tree
@@ -138,6 +139,7 @@ static MDNode* md_node_create(MDParserData *data) {
         } else {
             md_node_add_child(current, node);
         }
+        
     } else {
         data->p_current->content = node;
     }
@@ -164,7 +166,17 @@ static int md_enter_span(MD_SPANTYPE type, void* detail, void* userdata) {
 static int md_leave_span(MD_SPANTYPE type, void* detail, void* userdata) {
     MDParserData *data = userdata;
     size_t len = cxListSize(data->text_stack);
+    MDNode *current = get_current_textnode(data);
     MDNode *elm = NULL;
+    
+    if(current->text.ptr) {
+        // last node was a text node
+        // there is no leave event for text nodes, so we have to handle it here
+        // and remove it from the stack
+        cxListRemove(data->text_stack, len-1);
+        len--; // len is always > 1 here
+    }
+    
     if(len > 1) {
         cxListRemoveAndGet(data->text_stack, len-1, &elm);
     } else {
@@ -211,15 +223,18 @@ static int md_text(MD_TEXTTYPE type, const MD_CHAR* text, MD_SIZE size, void* us
             if(current->parent) {
                 current->parent->children_end = textnode;
             }
+            textstack_update_last_element(data->text_stack, textnode);
         } else {
             md_node_add_child(current, textnode);
+            cxListAdd(data->text_stack, textnode);
         }
+        
     } else {
         // root node
         data->p_current->content = textnode;
         cxListAdd(data->text_stack, textnode);
     }
-    
+      
     return 0;
 }
 
@@ -317,6 +332,7 @@ static const char* paragraph_style(MDPara *p) {
                 case 6: return EDITOR_STYLE_HEADING6;
             }
         }
+        case MD_BLOCK_QUOTE: return EDITOR_STYLE_QUOTE;
         case MD_BLOCK_CODE: return EDITOR_STYLE_CODE_BLOCK;
         default: return EDITOR_STYLE_PARAGRAPH;
     }
index c9e2a630e2afb0729efad4673198b8b9eb9d67a7..6d275ec7ac52b9396829ae419512da955140ccf0 100644 (file)
@@ -89,6 +89,7 @@ CX_TEST(test_parse_markdown_formatting_simple) {
     MDNode *t0;
     MDNode *t1;
     MDNode *t2;
+    MDNode *t3;
     
     CX_TEST_DO {
         doc = parse_markdown(CX_STR("test **bold** end"));
@@ -142,6 +143,58 @@ CX_TEST(test_parse_markdown_formatting_simple) {
         CX_TEST_ASSERT(t1->type == MD_SPAN_STRONG);
         CX_TEST_ASSERT(!cx_strcmp(mdnode_get_text(t1), CX_STR("bold end")));
         mddoc_free(doc);
+        
+        doc = parse_markdown(CX_STR("hello `code` hello *emphasis*"));
+        CX_TEST_ASSERT(doc);
+        CX_TEST_ASSERT(doc->content);
+        p0 = doc->content;
+        CX_TEST_ASSERT(p0->type == MD_BLOCK_P);
+        t0 = p0->content;
+        CX_TEST_ASSERT(t0->text.ptr);
+        CX_TEST_ASSERT(!cx_strcmp(cx_strcast(t0->text), CX_STR("hello ")));
+        t1 = t0->next;
+        CX_TEST_ASSERT(t1);
+        CX_TEST_ASSERT(t1->type == MD_SPAN_CODE);
+        CX_TEST_ASSERT(!cx_strcmp(mdnode_get_text(t1), CX_STR("code")));
+        t2 = t1->next;
+        CX_TEST_ASSERT(t2);
+        CX_TEST_ASSERT(t2->text.ptr);
+        CX_TEST_ASSERT(!cx_strcmp(cx_strcast(t2->text), CX_STR(" hello ")));
+        t3 = t2->next;
+        CX_TEST_ASSERT(t3);
+        CX_TEST_ASSERT(t3->type == MD_SPAN_EM);
+        CX_TEST_ASSERT(!cx_strcmp(mdnode_get_text(t3), CX_STR("emphasis")));
+        
+        doc = parse_markdown(CX_STR("test *begin __bold__ text* end"));
+        CX_TEST_ASSERT(doc);
+        CX_TEST_ASSERT(doc->content);
+        p0 = doc->content;
+        CX_TEST_ASSERT(p0->type == MD_BLOCK_P);
+        t0 = p0->content;
+        CX_TEST_ASSERT(t0);
+        CX_TEST_ASSERT(t0->text.ptr);
+        CX_TEST_ASSERT(!cx_strcmp(cx_strcast(t0->text), CX_STR("test ")));
+        t1 = t0->next;
+        CX_TEST_ASSERT(t1);
+        CX_TEST_ASSERT(!t1->text.ptr);
+        CX_TEST_ASSERT(t1->type == MD_SPAN_EM);
+        t2 = t1->next;
+        CX_TEST_ASSERT(t2);
+        CX_TEST_ASSERT(t2->text.ptr);
+        CX_TEST_ASSERT(!cx_strcmp(cx_strcast(t2->text), CX_STR(" end")));
+        MDNode *em_t0 = t1->children_begin;
+        CX_TEST_ASSERT(em_t0);
+        CX_TEST_ASSERT(em_t0->text.ptr);
+        CX_TEST_ASSERT(!cx_strcmp(cx_strcast(em_t0->text), CX_STR("begin ")));
+        MDNode *em_t1 = em_t0->next;
+        CX_TEST_ASSERT(em_t1);
+        CX_TEST_ASSERT(em_t1->type == MD_SPAN_STRONG);
+        CX_TEST_ASSERT(!cx_strcmp(mdnode_get_text(em_t1), CX_STR("bold")));
+        MDNode *em_t2 = em_t1->next;
+        CX_TEST_ASSERT(em_t2);
+        CX_TEST_ASSERT(!em_t2->next);
+        CX_TEST_ASSERT(em_t2->text.ptr);
+        CX_TEST_ASSERT(!cx_strcmp(cx_strcast(em_t2->text), CX_STR(" text")));
     }
 }