Przeglądaj źródła

Add a bunch more node actions

Billy Barrow 2 lat temu
rodzic
commit
2189f75ea5

+ 19 - 0
src/lib/NodeActions/Break.vala

@@ -0,0 +1,19 @@
+namespace GtkCommonMark.NodeActions {
+
+    public class Break : SimpleNodeAction {
+
+        public Break(CMark.Node node) {
+            base(node);
+        }
+
+        public override Gtk.TextTag get_tag(TagManager tags) {
+            return tags.none;
+        }
+
+        public override void at_end(Gtk.TextBuffer buffer, ref Gtk.TextIter iter) {
+            buffer.insert(ref iter, @"\n", -1);
+        }
+
+    }
+
+}

+ 43 - 0
src/lib/NodeActions/Code.vala

@@ -0,0 +1,43 @@
+namespace GtkCommonMark.NodeActions {
+
+    public class Code : SimpleNodeAction {
+
+        public Code(CMark.Node node) {
+            base(node);
+        }
+
+        public override Gtk.TextTag get_tag(TagManager tags) {
+            return tags.code;
+        }
+
+        public override void at_start(Gtk.TextBuffer buffer, ref Gtk.TextIter iter) {
+            var literal = node.get_literal();
+            if(literal != null) {
+                var glyph = buffer.create_tag(null);
+                glyph.weight = 200;
+                glyph.foreground_rgba = Gdk.RGBA() {
+                    red = 0.75f,
+                    green = 0.75f,
+                    blue = 0.75f,
+                    alpha = 1,
+                };
+
+                var newlines = literal.split("\n");
+                for(var i = 0; i < newlines.length; i++) {
+                    if(i != 0) {
+                        buffer.insert_with_tags(ref iter, "⮒\n", -1, glyph);
+                    }
+                    var spaces = newlines[i].split(" ");
+                    for(var j = 0; j < spaces.length; j++) {
+                        if(j != 0) {
+                            buffer.insert_with_tags(ref iter, "·", -1, glyph);
+                        }
+                        buffer.insert(ref iter, spaces[j], -1);
+                    }
+                }
+            }
+        }
+
+    }
+
+}

+ 16 - 0
src/lib/NodeActions/CodeBlock.vala

@@ -0,0 +1,16 @@
+namespace GtkCommonMark.NodeActions {
+
+    public class CodeBlock : Code {
+
+        public CodeBlock(CMark.Node node) {
+            base(node);
+        }
+
+        public override Gtk.TextTag get_tag(TagManager tags) {
+            return tags.code_block;
+        }
+
+
+    }
+
+}

+ 27 - 0
src/lib/NodeActions/Embed.vala

@@ -0,0 +1,27 @@
+namespace GtkCommonMark.NodeActions {
+
+    public class Embed : SimpleNodeAction {
+
+        private Gtk.Widget widget;
+        private Gtk.TextView text_view;
+
+        public Embed(CMark.Node node, Gtk.TextView text_view, Gtk.Widget widget) {
+            base(node);
+            this.widget = widget;
+            this.text_view = text_view;
+        }
+
+        public override Gtk.TextTag get_tag(TagManager tags) {
+            return tags.embed;
+        }
+
+        public override void at_start(Gtk.TextBuffer buffer, ref Gtk.TextIter iter) {        
+            var anchor = buffer.create_child_anchor(iter);
+            text_view.add_child_at_anchor(widget, anchor);
+            buffer.get_end_iter(out iter);
+            buffer.insert(ref iter, "\n", -1);
+        }
+
+    }
+
+}

+ 2 - 2
src/lib/NodeActions/Emphisis.vala

@@ -2,8 +2,8 @@ namespace GtkCommonMark.NodeActions {
 
     public class Emphisis : SimpleNodeAction {
 
-        public Emphisis(CMark.Node node, Gtk.TextMark start_mark) {
-            base(node, start_mark);
+        public Emphisis(CMark.Node node) {
+            base(node);
         }
 
         public override Gtk.TextTag get_tag(TagManager tags) {

+ 3 - 3
src/lib/NodeActions/Heading.vala

@@ -2,10 +2,10 @@
 
 namespace GtkCommonMark.NodeActions {
 
-    public class Heading : BlockNodeAction {
+    public class Heading : NewlineTerminatedNodeAction {
 
-        public Heading(CMark.Node node, Gtk.TextMark start_mark) {
-            base(node, start_mark);
+        public Heading(CMark.Node node) {
+            base(node);
         }
 
         public override Gtk.TextTag get_tag(TagManager tags) {

+ 20 - 0
src/lib/NodeActions/Item.vala

@@ -0,0 +1,20 @@
+
+
+namespace GtkCommonMark.NodeActions {
+
+    public class Item : SimpleNodeAction {
+
+        private int level = 0;
+
+        public Item(CMark.Node node) {
+            base(node);
+            level = self_nested_count();
+        }
+
+        public override Gtk.TextTag get_tag(TagManager tags) {
+            return tags.get_list_item(level);
+        }
+
+    }
+
+}

+ 26 - 5
src/lib/NodeActions/List.vala

@@ -2,18 +2,39 @@
 
 namespace GtkCommonMark.NodeActions {
 
-    public class List : BlockNodeAction {
+    public class List : SimpleNodeAction {
 
-        public List(CMark.Node node, Gtk.TextMark start_mark) {
-            base(node, start_mark);
+        private const string BULLET_CHAR = "•";
+
+        private bool numbered = false;
+        private int count = 1;
+        private int level = 0;
+
+        public List(CMark.Node node) {
+            base(node);
+            numbered = node.get_list_type() == CMark.LIST_TYPE.ORDERED;
+            count = node.get_list_start();
+            level = self_nested_count();
         }
 
         public override Gtk.TextTag get_tag(TagManager tags) {
-            return tags.none;
+            return tags.get_list(level);
         }
 
         public override void at_before_child(Gtk.TextBuffer buffer, ref Gtk.TextIter iter, CMark.Node child) {
-            buffer.insert(ref iter, "• ", -1);
+            if(!numbered) {
+                buffer.insert(ref iter, @"$BULLET_CHAR\t", -1);
+                return;
+            }
+
+            buffer.insert(ref iter, @"$count.\t", -1);
+            count++;
+        }
+
+        public override void at_end(Gtk.TextBuffer buffer, ref Gtk.TextIter iter) {
+            if(level == 0) {
+                buffer.insert(ref iter, "\n", -1);
+            }
         }
 
     }

+ 31 - 12
src/lib/NodeActions/NodeAction.vala

@@ -6,9 +6,8 @@ namespace GtkCommonMark.NodeActions {
         public unowned CMark.Node node {get; set;}
         public Gtk.TextMark start_mark {get; set;}
 
-        protected NodeAction(CMark.Node node, Gtk.TextMark start_mark) {
+        protected NodeAction(CMark.Node node) {
             this.node = node;
-            this.start_mark = start_mark;
         }
 
         public abstract void at_start(Gtk.TextBuffer buffer, ref Gtk.TextIter iter);
@@ -16,22 +15,35 @@ namespace GtkCommonMark.NodeActions {
         public abstract void at_after_end(Gtk.TextBuffer buffer, ref Gtk.TextIter iter);
 
         public abstract void at_before_child(Gtk.TextBuffer buffer, ref Gtk.TextIter iter, CMark.Node child);
+        public abstract void at_child_start(Gtk.TextBuffer buffer, ref Gtk.TextIter iter, CMark.Node child);
+        public abstract void at_child_end(Gtk.TextBuffer buffer, ref Gtk.TextIter iter, CMark.Node child);
         public abstract void at_after_child(Gtk.TextBuffer buffer, ref Gtk.TextIter iter, CMark.Node child);
 
         public abstract Gtk.TextTag get_tag(TagManager tags);
+
+        protected int self_nested_count() {
+            var type = node.get_type();
+            var counter = 0;
+            unowned var n = node.parent();
+            while(n != null && n.get_type() != CMark.NODE_TYPE.NONE) {
+                if(n.get_type() == type) {
+                    counter++;
+                }
+                n = n.parent();
+            }
+
+            return counter;
+        }
     }
 
     public class SimpleNodeAction : NodeAction {
 
-        public SimpleNodeAction(CMark.Node node, Gtk.TextMark start_mark) {
-            base(node, start_mark);
+        public SimpleNodeAction(CMark.Node node) {
+            base(node);
         }
 
         public override void at_start(Gtk.TextBuffer buffer, ref Gtk.TextIter iter) {
-            var literal = node.get_literal();
-            if(literal != null) {
-                buffer.insert(ref iter, literal, -1);
-            }
+            // No-op
         }
         public override void at_end(Gtk.TextBuffer buffer, ref Gtk.TextIter iter) {
             // No-op
@@ -42,6 +54,12 @@ namespace GtkCommonMark.NodeActions {
         public override void at_before_child(Gtk.TextBuffer buffer, ref Gtk.TextIter iter, CMark.Node child) {
             // No-op
         }
+        public override void at_child_start(Gtk.TextBuffer buffer, ref Gtk.TextIter iter, CMark.Node child) {
+            // No-op
+        }
+        public override void at_child_end(Gtk.TextBuffer buffer, ref Gtk.TextIter iter, CMark.Node child) {
+            // No-op
+        }
         public override void at_after_child(Gtk.TextBuffer buffer, ref Gtk.TextIter iter, CMark.Node child) {
             // No-op
         }
@@ -51,13 +69,14 @@ namespace GtkCommonMark.NodeActions {
 
     }
 
-    public class BlockNodeAction : SimpleNodeAction {
+    public class NewlineTerminatedNodeAction : SimpleNodeAction {
 
-        public BlockNodeAction(CMark.Node node, Gtk.TextMark start_mark) {
-            base(node, start_mark);
+        public NewlineTerminatedNodeAction(CMark.Node node) {
+            base(node);
         }
+
         public override void at_end(Gtk.TextBuffer buffer, ref Gtk.TextIter iter) {
-            buffer.insert(ref iter, "\n", -1);
+            buffer.insert(ref iter, @"\n", -1);
         }
     }
 

+ 19 - 0
src/lib/NodeActions/Paragraph.vala

@@ -0,0 +1,19 @@
+namespace GtkCommonMark.NodeActions {
+
+    public class Paragraph : SimpleNodeAction {
+
+        public Paragraph(CMark.Node node) {
+            base(node);
+        }
+
+        public override Gtk.TextTag get_tag(TagManager tags) {
+            return tags.paragraph;
+        }
+
+        public override void at_end(Gtk.TextBuffer buffer, ref Gtk.TextIter iter) {
+            buffer.insert(ref iter, "\n", -1);
+        }
+
+    }
+
+}

+ 28 - 0
src/lib/NodeActions/Quote.vala

@@ -0,0 +1,28 @@
+namespace GtkCommonMark.NodeActions {
+
+    public class Quote : SimpleNodeAction {
+
+        public Quote(CMark.Node node) {
+            base(node);
+        }
+
+        public override Gtk.TextTag get_tag(TagManager tags) {
+            return tags.get_blockquote(self_nested_count());
+        }
+
+        public override void at_start(Gtk.TextBuffer buffer, ref Gtk.TextIter iter) {
+            var glyph = buffer.create_tag(null);
+            glyph.weight = 200;
+            glyph.scale = 2;
+
+            buffer.insert_with_tags(ref iter, "“\t", -1, glyph);
+            buffer.insert(ref iter, @"QL-$(self_nested_count())", -1);
+        }
+
+        public override void at_end(Gtk.TextBuffer buffer, ref Gtk.TextIter iter) {
+            //  buffer.insert(ref iter, @"\nQL-$(self_nested_count())\n", -1);
+        }
+
+    }
+
+}

+ 2 - 2
src/lib/NodeActions/Strong.vala

@@ -2,8 +2,8 @@ namespace GtkCommonMark.NodeActions {
 
     public class Strong : SimpleNodeAction {
 
-        public Strong(CMark.Node node, Gtk.TextMark start_mark) {
-            base(node, start_mark);
+        public Strong(CMark.Node node) {
+            base(node);
         }
 
         public override Gtk.TextTag get_tag(TagManager tags) {

+ 22 - 0
src/lib/NodeActions/Text.vala

@@ -0,0 +1,22 @@
+namespace GtkCommonMark.NodeActions {
+
+    public class Text : SimpleNodeAction {
+
+        public Text(CMark.Node node) {
+            base(node);
+        }
+
+        public override Gtk.TextTag get_tag(TagManager tags) {
+            return tags.text;
+        }
+
+        public override void at_start(Gtk.TextBuffer buffer, ref Gtk.TextIter iter) {
+            var literal = node.get_literal();
+            if(literal != null) {
+                buffer.insert(ref iter, literal, -1);
+            }
+        }
+
+    }
+
+}

+ 27 - 0
src/lib/NodeActions/ThematicBreak.vala

@@ -0,0 +1,27 @@
+namespace GtkCommonMark.NodeActions {
+
+    public class ThematicBreak : SimpleNodeAction {
+
+        private Gtk.TextView text_view;
+
+        public ThematicBreak(CMark.Node node, Gtk.TextView text_view) {
+            base(node);
+            this.text_view = text_view;
+        }
+
+        public override Gtk.TextTag get_tag(TagManager tags) {
+            return tags.seperator;
+        }
+
+        public override void at_start(Gtk.TextBuffer buffer, ref Gtk.TextIter iter) {        
+            var anchor = buffer.create_child_anchor(iter);
+            var seperator = new Gtk.Separator(Gtk.Orientation.HORIZONTAL);
+            seperator.width_request = 200;
+            text_view.add_child_at_anchor(seperator, anchor);
+            buffer.get_end_iter(out iter);
+            buffer.insert(ref iter, "\n", -1);
+        }
+
+    }
+
+}

+ 80 - 66
src/lib/Reader.vala

@@ -6,14 +6,16 @@ namespace GtkCommonMark {
 
         private TagManager tags;
         private Gtk.TextBuffer buffer;
+        private Gtk.TextView text_view;
 
         private CMark.Iter cm_iter = null;
         private Gtk.TextIter tb_iter;
         private List<NodeActions.NodeAction> node_actions;
 
-        public Reader(Gtk.TextBuffer buffer, TagManager tag_manager) {
+        public Reader(Gtk.TextBuffer buffer, Gtk.TextView text_view, TagManager tag_manager) {
             this.tags = tag_manager;
             this.buffer = buffer;
+            this.text_view = text_view;
         }
 
         public void append_node(CMark.Node root) {
@@ -29,8 +31,9 @@ namespace GtkCommonMark {
                 }
 
                 unowned var node = cm_iter.get_node();
-                var start_mark = buffer.create_mark(null, tb_iter, true);
-                var action = build_action_for_node(node, start_mark);
+                
+                var action = build_action_for_node(node);
+
                 node_actions.prepend(action);
 
                 prepare_for_child();
@@ -55,12 +58,16 @@ namespace GtkCommonMark {
         }
 
         private void prepare_for_child() {
+            var child_action = node_actions.nth_data(0);
             if(node_actions.length() < 2) {
+                child_action.start_mark = buffer.create_mark(null, tb_iter, true);
                 return;
             }
-            var child_action = node_actions.nth_data(0);
+
             var parent_action = node_actions.nth_data(1);
             parent_action.at_before_child(buffer, ref tb_iter, child_action.node);
+            child_action.start_mark = buffer.create_mark(null, tb_iter, true);
+            parent_action.at_child_start(buffer, ref tb_iter, child_action.node);
         }
 
         private void finalise_after_child() {
@@ -133,136 +140,143 @@ namespace GtkCommonMark {
             
         }
 
-        protected virtual NodeActions.NodeAction build_action_for_node(CMark.Node node, Gtk.TextMark start_mark) {
+        protected virtual NodeActions.NodeAction build_action_for_node(CMark.Node node) {
             var type = node.get_type();
+            print(@"Building type $type\n");
             switch (type) {
                 case CMark.NODE_TYPE.BLOCK_QUOTE:
-                    return build_action_for_block_quote(node, start_mark);
+                    return build_action_for_block_quote(node);
                 case CMark.NODE_TYPE.LIST:
-                    return build_action_for_list(node, start_mark);
+                    return build_action_for_list(node);
                 case CMark.NODE_TYPE.ITEM:
-                    return build_action_for_item(node, start_mark);
+                    return build_action_for_item(node);
                 case CMark.NODE_TYPE.CODE_BLOCK:
-                    return build_action_for_code_block(node, start_mark);
+                    return build_action_for_code_block(node);
                 case CMark.NODE_TYPE.HTML_BLOCK:
-                    return build_action_for_html_block(node, start_mark);
+                    return build_action_for_html_block(node);
                 case CMark.NODE_TYPE.CUSTOM_BLOCK:
-                    return build_action_for_custom_block(node, start_mark);
+                    return build_action_for_custom_block(node);
                 case CMark.NODE_TYPE.PARAGRAPH:
-                    return build_action_for_paragraph(node, start_mark);
+                    return build_action_for_paragraph(node);
                 case CMark.NODE_TYPE.HEADING:
-                    return build_action_for_heading(node, start_mark);
+                    return build_action_for_heading(node);
                 case CMark.NODE_TYPE.THEMATIC_BREAK:
-                    return build_action_for_thematic_break(node, start_mark);
+                    return build_action_for_thematic_break(node);
                 case CMark.NODE_TYPE.TEXT:
-                    return build_action_for_text(node, start_mark);
+                    return build_action_for_text(node);
                 case CMark.NODE_TYPE.SOFTBREAK:
-                    return build_action_for_soft_break(node, start_mark);
+                    return build_action_for_soft_break(node);
                 case CMark.NODE_TYPE.LINEBREAK:
-                    return build_action_for_line_break(node, start_mark);
+                    return build_action_for_line_break(node);
                 case CMark.NODE_TYPE.CODE:
-                    return build_action_for_code(node, start_mark);
+                    return build_action_for_code(node);
                 case CMark.NODE_TYPE.HTML_INLINE:
-                    return build_action_for_inline_html(node, start_mark);
+                    return build_action_for_inline_html(node);
                 case CMark.NODE_TYPE.CUSTOM_INLINE:
-                    return build_action_for_inline_custom(node, start_mark);
+                    return build_action_for_inline_custom(node);
                 case CMark.NODE_TYPE.EMPH:
-                    return build_action_for_emphisis(node, start_mark);
+                    return build_action_for_emphisis(node);
                 case CMark.NODE_TYPE.STRONG:
-                    return build_action_for_bold(node, start_mark);
+                    return build_action_for_bold(node);
                 case CMark.NODE_TYPE.LINK:
-                    return build_action_for_link(node, start_mark);
+                    return build_action_for_link(node);
                 case CMark.NODE_TYPE.IMAGE:
-                    return build_action_for_embed(node, start_mark);
+                    return build_action_for_embed(node);
 
                 default:
-                    return build_default_action(node, start_mark);
+                    return build_default_action(node);
             }
         }
 
 
-        protected virtual NodeActions.NodeAction build_action_for_block_quote(CMark.Node node, Gtk.TextMark start_mark) {
-            return build_default_action(node, start_mark);
+        protected virtual NodeActions.NodeAction build_action_for_block_quote(CMark.Node node) {
+            return new NodeActions.Quote(node);
         }
 
-        protected virtual NodeActions.NodeAction build_action_for_list(CMark.Node node, Gtk.TextMark start_mark) {
-            return new NodeActions.List(node, start_mark);
+        protected virtual NodeActions.NodeAction build_action_for_list(CMark.Node node) {
+            return new NodeActions.List(node);
         }
 
-        protected virtual NodeActions.NodeAction build_action_for_item(CMark.Node node, Gtk.TextMark start_mark) {
-            return build_default_action(node, start_mark);
+        protected virtual NodeActions.NodeAction build_action_for_item(CMark.Node node) {
+            return new NodeActions.Item(node);
         }
 
-        protected virtual NodeActions.NodeAction build_action_for_code_block(CMark.Node node, Gtk.TextMark start_mark) {
-            return build_default_action(node, start_mark);
+        protected virtual NodeActions.NodeAction build_action_for_code_block(CMark.Node node) {
+            return new NodeActions.CodeBlock(node);
         }
 
-        protected virtual NodeActions.NodeAction build_action_for_html_block(CMark.Node node, Gtk.TextMark start_mark) {
-            return build_default_action(node, start_mark);
+        protected virtual NodeActions.NodeAction build_action_for_html_block(CMark.Node node) {
+            return build_default_action(node);
         }
 
-        protected virtual NodeActions.NodeAction build_action_for_custom_block(CMark.Node node, Gtk.TextMark start_mark) {
-            return build_default_action(node, start_mark);
+        protected virtual NodeActions.NodeAction build_action_for_custom_block(CMark.Node node) {
+            return build_default_action(node);
         }
 
-        protected virtual NodeActions.NodeAction build_action_for_paragraph(CMark.Node node, Gtk.TextMark start_mark) {
-            return build_default_action(node, start_mark);
+        protected virtual NodeActions.NodeAction build_action_for_paragraph(CMark.Node node) {
+            return new NodeActions.Paragraph(node);
         }
 
-        protected virtual NodeActions.NodeAction build_action_for_heading(CMark.Node node, Gtk.TextMark start_mark) {
-            return new NodeActions.Heading(node, start_mark);
+        protected virtual NodeActions.NodeAction build_action_for_heading(CMark.Node node) {
+            return new NodeActions.Heading(node);
         }
 
-        protected virtual NodeActions.NodeAction build_action_for_thematic_break(CMark.Node node, Gtk.TextMark start_mark) {
-            return build_default_action(node, start_mark);
+        protected virtual NodeActions.NodeAction build_action_for_thematic_break(CMark.Node node) {
+            return new NodeActions.ThematicBreak(node, text_view);
         }
 
         // Inline Elements
-        protected virtual NodeActions.NodeAction build_action_for_text(CMark.Node node, Gtk.TextMark start_mark) {
-            return build_default_action(node, start_mark);
+        protected virtual NodeActions.NodeAction build_action_for_text(CMark.Node node) {
+            return new NodeActions.Text(node);
         }
 
-        protected virtual NodeActions.NodeAction build_action_for_soft_break(CMark.Node node, Gtk.TextMark start_mark) {
-            return build_default_action(node, start_mark);
+        protected virtual NodeActions.NodeAction build_action_for_soft_break(CMark.Node node) {
+            return build_default_action(node);
         }
 
-        protected virtual NodeActions.NodeAction build_action_for_line_break(CMark.Node node, Gtk.TextMark start_mark) {
-            return build_default_action(node, start_mark);
+        protected virtual NodeActions.NodeAction build_action_for_line_break(CMark.Node node) {
+            return new NodeActions.Break(node);
         }
 
-        protected virtual NodeActions.NodeAction build_action_for_code(CMark.Node node, Gtk.TextMark start_mark) {
-            return build_default_action(node, start_mark);
+        protected virtual NodeActions.NodeAction build_action_for_code(CMark.Node node) {
+            return new NodeActions.Code(node);
         }
 
-        protected virtual NodeActions.NodeAction build_action_for_inline_html(CMark.Node node, Gtk.TextMark start_mark) {
-            return build_default_action(node, start_mark);
+        protected virtual NodeActions.NodeAction build_action_for_inline_html(CMark.Node node) {
+            return build_default_action(node);
         }
 
-        protected virtual NodeActions.NodeAction build_action_for_inline_custom(CMark.Node node, Gtk.TextMark start_mark) {
-            return build_default_action(node, start_mark);
+        protected virtual NodeActions.NodeAction build_action_for_inline_custom(CMark.Node node) {
+            return build_default_action(node);
         }
 
-        protected virtual NodeActions.NodeAction build_action_for_emphisis(CMark.Node node, Gtk.TextMark start_mark) {
-            return new NodeActions.Emphisis(node, start_mark);
+        protected virtual NodeActions.NodeAction build_action_for_emphisis(CMark.Node node) {
+            return new NodeActions.Emphisis(node);
         }
 
-        protected virtual NodeActions.NodeAction build_action_for_bold(CMark.Node node, Gtk.TextMark start_mark) {
-            return new NodeActions.Strong(node, start_mark);
+        protected virtual NodeActions.NodeAction build_action_for_bold(CMark.Node node) {
+            return new NodeActions.Strong(node);
         }
 
-        protected virtual NodeActions.NodeAction build_action_for_link(CMark.Node node, Gtk.TextMark start_mark) {
-            return build_default_action(node, start_mark);
+        protected virtual NodeActions.NodeAction build_action_for_link(CMark.Node node) {
+            return build_default_action(node);
         }
 
-        protected virtual NodeActions.NodeAction build_action_for_embed(CMark.Node node, Gtk.TextMark start_mark) {
-            return build_default_action(node, start_mark);
+        protected virtual NodeActions.NodeAction build_action_for_embed(CMark.Node node) {
+            return new NodeActions.Embed(node, text_view, build_embed_widget(node));
         }
 
-        protected virtual NodeActions.NodeAction build_default_action(CMark.Node node, Gtk.TextMark start_mark) {
+        protected virtual NodeActions.NodeAction build_default_action(CMark.Node node) {
             if(is_block(node.get_type())) {
-                return new NodeActions.BlockNodeAction(node, start_mark);
+                return new NodeActions.NewlineTerminatedNodeAction(node);
             }
-            return new NodeActions.SimpleNodeAction(node, start_mark);
+            return new NodeActions.SimpleNodeAction(node);
+        }
+
+        protected virtual Gtk.Widget build_embed_widget(CMark.Node node) {
+            var widget = new Gtk.Image.from_file(node.get_url());
+            widget.set_size_request(500, 500);
+            return widget;
         }
         
     }

+ 131 - 5
src/lib/TagManager.vala

@@ -6,6 +6,14 @@ namespace GtkCommonMark {
 
         private Gtk.TextBuffer buffer;
 
+        public int page_margin {get {
+            return 18;
+        }}
+
+        private Gee.HashMap<int, Gtk.TextTag> list_tags = new Gee.HashMap<int, Gtk.TextTag>();
+        private Gee.HashMap<int, Gtk.TextTag> list_item_tags = new Gee.HashMap<int, Gtk.TextTag>();
+        private Gee.HashMap<int, Gtk.TextTag> blockquote_tags = new Gee.HashMap<int, Gtk.TextTag>();
+
         public TagManager(Gtk.TextBuffer buffer) {
             this.buffer = buffer;
             build_tags();
@@ -24,13 +32,18 @@ namespace GtkCommonMark {
             heading_l5 = buffer.create_tag(null);
             heading_l6 = buffer.create_tag(null);
 
+            paragraph = buffer.create_tag(null);
+
+            text = buffer.create_tag(null);
             emphisis = buffer.create_tag(null);
             strong = buffer.create_tag(null);
 
             code = buffer.create_tag(null);
             code_block = buffer.create_tag(null);
 
-            quote = buffer.create_tag(null);
+            embed = buffer.create_tag(null);
+            seperator = buffer.create_tag(null);
+
         }
 
         private void update_tags() {
@@ -44,6 +57,46 @@ namespace GtkCommonMark {
             emphisis.style = Pango.Style.ITALIC;
             strong.weight = 800;
 
+            embed.size = 0;
+
+            paragraph.pixels_below_lines = 9;
+            paragraph.pixels_above_lines = 9;
+
+            seperator.justification = Gtk.Justification.CENTER;
+            seperator.pixels_above_lines = 9;
+            seperator.pixels_below_lines = 9;
+
+            code.family = "monospace";
+            code.word = true;
+            code.background_full_height = true;
+            code.background_rgba = Gdk.RGBA() {
+                red = 0.95f,
+                green = 0.95f,
+                blue = 0.95f,
+                alpha = 1,
+            };
+            code.foreground_rgba = Gdk.RGBA() {
+                red = 0.4f,
+                green = 0,
+                blue = 0,
+                alpha = 1,
+            };
+
+            code_block.family = "monospace";
+            code_block.wrap_mode = Gtk.WrapMode.CHAR;
+            code_block.allow_breaks = true;
+            code_block.paragraph_background_rgba = Gdk.RGBA() {
+                red = 0.95f,
+                green = 0.95f,
+                blue = 0.95f,
+                alpha = 1,
+            };
+            code_block.foreground_rgba = Gdk.RGBA() {
+                red = 0.4f,
+                green = 0,
+                blue = 0,
+                alpha = 1,
+            };
         }
 
         public Gtk.TextTag none {get; private set;}
@@ -57,14 +110,17 @@ namespace GtkCommonMark {
         public Gtk.TextTag heading_l5 {get; private set;}
         public Gtk.TextTag heading_l6 {get; private set;}
 
+        public Gtk.TextTag paragraph {get; private set;}
+        
+        public Gtk.TextTag text {get; private set;}
         public Gtk.TextTag emphisis {get; private set;}
         public Gtk.TextTag strong {get; private set;}
-        public Gtk.TextTag underline {get; private set;}
 
         public Gtk.TextTag code {get; private set;}
         public Gtk.TextTag code_block {get; private set;}
 
-        public Gtk.TextTag quote {get; private set;}
+        public Gtk.TextTag embed {get; private set;}
+        public Gtk.TextTag seperator {get; private set;}
 
 
         public Gtk.TextTag get_heading(int level) {
@@ -87,10 +143,80 @@ namespace GtkCommonMark {
             }
         }
 
-        private void configure_heading (Gtk.TextTag tag, int level) {
+        public virtual Gtk.TextTag get_list(int level) {
+            if(!list_tags.has_key(level)) {
+                create_list_tag_pair(level);
+            }
+            return list_tags.get(level);
+        }
+
+        public virtual Gtk.TextTag get_list_item(int level) {
+            if(!list_item_tags.has_key(level)) {
+                create_list_tag_pair(level);
+            }
+            return list_item_tags.get(level);
+        }
+
+        private void create_list_tag_pair(int level) {
+            var list_tag = buffer.create_tag(null);
+            var item_tag = buffer.create_tag(null);
+            configure_list(level, list_tag, item_tag);
+            list_tags.set(level, list_tag);
+            list_item_tags.set(level, item_tag);
+        }
+
+        protected virtual void configure_heading (Gtk.TextTag tag, int level) {
             tag.size_points = 26 - (level * 2);
+            tag.pixels_below_lines = 18;
+            tag.pixels_above_lines = 18;
+            tag.weight = 700;
+        }
+
+        protected virtual void configure_list (int level, Gtk.TextTag list_tag, Gtk.TextTag item_tag) {
+            const int list_indent = 24;
+            var bullet_margin = page_margin + ((level+1) * list_indent);
+            var item_margin = bullet_margin + list_indent;
+
+            list_tag.indent = -list_indent;
+            list_tag.left_margin = bullet_margin;
+            var tabs = new Pango.TabArray(2, true);
+            tabs.set_tab(0, Pango.TabAlign.LEFT, 0);
+            tabs.set_tab(1, Pango.TabAlign.LEFT, list_indent);
+            list_tag.tabs = tabs;
+
+            item_tag.indent = 0;
+            item_tag.left_margin = item_margin;
+        }
+
+        public virtual Gtk.TextTag get_blockquote (int level) {
+            if(!blockquote_tags.has_key(level)) {
+                var tag = buffer.create_tag(null);
+                configure_blockquote(level, tag);
+                blockquote_tags.set(level, tag);
+            }
+            return blockquote_tags.get(level);
+        }
+
+        protected virtual void configure_blockquote (int level, Gtk.TextTag tag) {
+            const int quote_indent = 9;
+            const int quote_text_distance = 24;
+            var quote_margin = ((level+1) * quote_indent) + quote_text_distance;
+
+            
+            tag.indent = -quote_text_distance;
+            tag.left_margin = quote_margin;
+            print(tag.left_margin.to_string());
+            print(@" and QL-$level has margin of $quote_margin px\n");
+            var tabs = new Pango.TabArray(2, true);
+            tabs.set_tab(0, Pango.TabAlign.LEFT, 0);
+            tabs.set_tab(1, Pango.TabAlign.LEFT, quote_text_distance);
+            tag.tabs = tabs;
+            tag.size_points = 14;
+            tag.family = "serif";
+            tag.foreground = "grey";
+            tag.accumulative_margin = true;
         }
 
     }
 
-}
+}

+ 9 - 0
src/lib/meson.build

@@ -6,6 +6,7 @@ dependencies = [
     dependency('glib-2.0'),
     dependency('gobject-2.0'),
     dependency('gio-2.0'),
+    dependency('gee-0.8'),
     dependency('gtk4'),
     meson.get_compiler('vala').find_library('libcmark', dirs: vapi_dir),
     meson.get_compiler('c').find_library('cmark'),
@@ -19,6 +20,14 @@ sources += files('NodeActions/Emphisis.vala')
 sources += files('NodeActions/Strong.vala')
 sources += files('NodeActions/List.vala')
 sources += files('NodeActions/Item.vala')
+sources += files('NodeActions/Paragraph.vala')
+sources += files('NodeActions/Embed.vala')
+sources += files('NodeActions/Text.vala')
+sources += files('NodeActions/Break.vala')
+sources += files('NodeActions/Quote.vala')
+sources += files('NodeActions/ThematicBreak.vala')
+sources += files('NodeActions/Code.vala')
+sources += files('NodeActions/CodeBlock.vala')
 
 libgtkcmark = shared_library('gtkcommonmark', sources,
     dependencies: dependencies,

+ 4 - 4
src/lib/vapi/libcmark.vapi

@@ -73,8 +73,8 @@
        HEADING,
        THEMATIC_BREAK,
  
-       FIRST_BLOCK, // = DOCUMENT,
-       LAST_BLOCK, // = THEMATIC_BREAK,
+    //     FIRST_BLOCK, // = DOCUMENT,
+    //     LAST_BLOCK, // = THEMATIC_BREAK,
  
        /* Inline */
        TEXT,
@@ -88,8 +88,8 @@
        LINK,
        IMAGE,
  
-       FIRST_INLINE, // = TEXT,
-       LAST_INLINE // = IMAGE,
+    //     FIRST_INLINE, // = TEXT,
+    //     LAST_INLINE // = IMAGE,
      }
  
  

+ 7 - 7
src/viewer/Main.vala

@@ -29,16 +29,16 @@ int main (string[] argv) {
 
         //  buffer.end_irreversible_action();
 
-        var reader = new GtkCommonMark.Reader(buffer, tags);
-        var file = GLib.FileStream.open ("/home/bbarrow/Documents/Recipes/canned_spaghetti_toast/recipe.md", "r");
-        //  var file = GLib.FileStream.open ("test.md", "r");
+        var reader = new GtkCommonMark.Reader(buffer, text_view, tags);
+        //  var file = GLib.FileStream.open ("/home/bbarrow/Documents/Recipes/canned_spaghetti_toast/recipe.md", "r");
+        var file = GLib.FileStream.open ("test.md", "r");
         var root = CMark.Node.parse_file (file, CMark.OPT.DEFAULT);
         reader.append_node (root);
 
-        text_view.top_margin = 18;
-        text_view.bottom_margin = 18;
-        text_view.left_margin = 18;
-        text_view.right_margin = 18;
+        text_view.top_margin = tags.page_margin;
+        text_view.bottom_margin = tags.page_margin;
+        text_view.left_margin = tags.page_margin;
+        text_view.right_margin = tags.page_margin;
 
         var srcolled_window = new Gtk.ScrolledWindow ();
         srcolled_window.set_policy (PolicyType.NEVER, PolicyType.AUTOMATIC);

+ 89 - 1
test.md

@@ -1,3 +1,91 @@
 # Hello World
 
-This *is* a **test** mate.
+This *is* a **test** mate.
+This *could* be a new line
+
+And this **should** be a new paragraph!
+
+Horizontal rule please
+
+---
+
+I am some inline `code thing` that should be looked at `how_neat();`.
+
+```
+Now we have a code block
+It is preformatted text.
+```
+
+It can be used to show source code such as the code for the CodeBlock action
+
+```
+namespace GtkCommonMark.NodeActions {
+
+    public class CodeBlock : SimpleNodeAction {
+
+        public CodeBlock(CMark.Node node) {
+            base(node);
+        }
+
+        public override Gtk.TextTag get_tag(TagManager tags) {
+            return tags.code_block;
+        }
+
+    }
+
+}
+```
+
+- I am
+- The example of
+- A bullet
+- List
+    - I am unordered
+        - And I can be nested
+        - (Isn't that neat)
+    - Which means I have no order and just have few dotty bois
+- So there you go
+
+
+> This is my cool quote, what do you think of it?
+> > It's cool, but maybe it could use some nesting if you get what I'm on about here.
+
+1. I am
+2. The example of
+3. A numbered
+4. List
+    1. I am ordered
+    2. So I have numbers
+        1. They count up,
+            1. I want to know when this will break
+            2. Maybe here?
+                1. Or maybe up here?
+                2. Here is a long bit of text to make the line real long so it wraps
+            3. Hahahahah
+        2. And can start from any number
+    3. Nesting is cool
+5. Hopefully it works
+
+<!-- ![House Photo](/home/bbarrow/Pictures/House/1943301509.jpg) -->
+
+10. This list starts from 10
+10. The MD does not incriement the number
+10. But it should be incremented in the rendered version!
+
+## A copy of the exact same list from before
+
+1. I am
+2. The example of
+3. A numbered
+4. List
+    1. I am ordered
+    2. So I have numbers
+        1. They count up,
+            1. I want to know when this will break
+            2. Maybe here?
+                1. Or maybe up here?
+                2. Here is a long bit of text to make the line real long so it wraps
+            3. Hahahahah
+        2. And can start from any number
+    3. Nesting is cool
+5. Hopefully it works