示例#1
0
        private MarkdownNode Parse(string rawMarkdown)
        {
            MarkdownNode root = new MarkdownNode()
            {
                Type = MarkdownType.Root
            };

            _current = root;

            string[] lines = rawMarkdown.Split(new[] { "\r\n", "\r", "\n" },
                                               StringSplitOptions.None);

            foreach (var line in lines)
            {
                foreach (var handler in _handlers)
                {
                    if (handler.HandleLine(_current, line))
                    {
                        break;
                    }
                }
            }

            return(root);
        }
示例#2
0
        public bool HandleLine(MarkdownNode context, string line)
        {
            line = line.Trim();
            bool isBullet;
            int  skip;

            if (line.StartsWith("-"))
            {
                isBullet = true;
                skip     = 1;
            }
            else if (line.StartsWith("#."))
            {
                isBullet = false;
                skip     = 2;
            }
            else
            {
                return(false);
            }

            var bulletNode = new MarkdownNode()
            {
                Type = isBullet ? MarkdownType.Bulleted : MarkdownType.Numbered,
            };

            context.AddChild(bulletNode);

            AppendParsedTextTo(bulletNode, line.Substring(skip).Trim());

            return(true);
        }
        public bool HandleLine(MarkdownNode context, string line)
        {
            line = line.Trim();
            var headingTag = GetHeadingTag(line);

            if (headingTag == null)
            {
                return(false);
            }

            MarkdownType type;

            switch (headingTag)
            {
            case "#": type = MarkdownType.Heading1; break;

            case "##": type = MarkdownType.Heading2; break;

            case "###": type = MarkdownType.Heading3; break;

            default: return(false);
            }

            string headingText = line.Substring(headingTag.Length).Trim();
            var    node        = new MarkdownNode()
            {
                Type = type,
                Text = headingText
            };

            context.AddChild(node);
            return(true);
        }
示例#4
0
        private bool nextSatisfies(int i, MarkdownNode parent, Func <MarkdownNode, bool> predicate)
        {
            i += 1;
            if (i < 0 || i >= parent.Children.Count)
            {
                return(false);
            }
            var node = parent.Children[i];

            return(predicate(node));
        }
示例#5
0
 public void RemoveChild(MarkdownNode child)
 {
     if (child.Parent == this)
     {
         _children.Remove(child);
         child.Parent = null;
         if (_children.Count == 0)
         {
             _children = null;
         }
     }
 }
示例#6
0
 public void AddChild(MarkdownNode child)
 {
     if (child.Parent != null)
     {
         child.Parent.RemoveChild(child);
     }
     child.Parent = this;
     if (_children == null)
     {
         _children = new List <MarkdownNode>();
     }
     _children.Add(child);
 }
        public bool HandleLine(MarkdownNode context, string line)
        {
            line = line.Trim();
            var para = new MarkdownNode()
            {
                Type = MarkdownType.Paragraph
            };

            context.AddChild(para);

            AppendParsedTextTo(para, line);

            return(true);
        }
示例#8
0
        protected void AppendParsedTextTo(MarkdownNode parent, string line)
        {
            var ranges = Parse(line);

            Stack <MarkdownNode> stack = new Stack <MarkdownNode>();

            foreach (var range in ranges)
            {
                if (range.IsEmpty)
                {
                    throw new Exception("Unexpected empty markdown paragraph range.");
                }
                stack.Clear();
                stack.Push(new MarkdownNode()
                {
                    Type = MarkdownType.Text, Text = range.ExtractText(line)
                });
                if (range.Underline)
                {
                    stack.Push(new MarkdownNode()
                    {
                        Type = MarkdownType.Underline
                    });
                }
                if (range.Italic)
                {
                    stack.Push(new MarkdownNode()
                    {
                        Type = MarkdownType.Italic
                    });
                }
                if (range.Bold)
                {
                    stack.Push(new MarkdownNode()
                    {
                        Type = MarkdownType.Bold
                    });
                }
                var node = parent;
                while (stack.Count > 0)
                {
                    var child = stack.Pop();
                    node.AddChild(child);
                    node = child;
                }
            }
        }
示例#9
0
        private void RenderNode(MarkdownNode node, StringBuilder builder)
        {
            string openTag  = null;
            string closeTag = null;

            switch (node.Type)
            {
            case MarkdownType.Heading1: openTag = "<span style=\"font-size: 140%; font-weight: bold\">"; closeTag = "</span>"; break;

            case MarkdownType.Heading2: openTag = "<span style=\"font-size: 120%; font-weight: bold; font-style=italic;\">"; closeTag = "</span>"; break;

            case MarkdownType.Heading3: openTag = "<span style=\"font-size: 105%; font-weight: bold\">"; closeTag = "</span>"; break;

            // case MarkdownType.Bulleted: openTag = "<ul>"; closeTag = "</ul>"; break;
            // case MarkdownType.Numbered: openTag = "<ol>"; closeTag = "</ol>"; break;
            case MarkdownType.Bold: openTag = "<b>"; closeTag = "</b>"; break;

            case MarkdownType.Italic: openTag = "<i>"; closeTag = "</i>"; break;

            case MarkdownType.Underline: openTag = "<u>"; closeTag = "</u>"; break;

            //case MarkdownType.BlankLine: openTag = null; closeTag = "<br>"; break;
            default: break;
            }
            if (openTag != null)
            {
                builder.Append(openTag);
            }
            if (node.Text != null)
            {
                builder.Append(WebUtility.HtmlEncode(node.Text));
            }

            for (int i = 0; i < node.Children.Count; ++i)
            {
                var child = node.Children[i];
                if (child.Type == MarkdownType.Bulleted)
                {
                    if (!previousSatisfies(i, node, n => n.Type == MarkdownType.Bulleted))
                    {
                        builder.AppendLine();
                        builder.AppendLine("<ul>");
                    }

                    builder.Append("<li>");
                    RenderNode(child, builder);
                    builder.AppendLine("</li>");

                    if (!nextSatisfies(i, node, n => n.Type == MarkdownType.Bulleted))
                    {
                        builder.AppendLine();
                        builder.AppendLine("</ul>");
                    }
                }
                else if (child.Type == MarkdownType.Numbered)
                {
                    if (!previousSatisfies(i, node, n => n.Type == MarkdownType.Numbered))
                    {
                        builder.AppendLine();
                        builder.AppendLine("<ol>");
                    }

                    builder.Append("<li>");
                    RenderNode(child, builder);
                    builder.AppendLine("</li>");

                    if (!nextSatisfies(i, node, n => n.Type == MarkdownType.Numbered))
                    {
                        builder.AppendLine();
                        builder.AppendLine("</ol>");
                    }
                }
                else if (child.Type == MarkdownType.Paragraph)
                {
                    if (!previousSatisfies(i, node, n => n.Type == MarkdownType.Paragraph))
                    {
                        builder.AppendLine();
                        builder.AppendLine("<p>");
                    }
                    else
                    {
                        builder.AppendLine("<br>");
                    }

                    RenderNode(child, builder);

                    if (!nextSatisfies(i, node, n => n.Type == MarkdownType.Paragraph))
                    {
                        builder.AppendLine();
                        builder.AppendLine("</p>");
                    }
                }
                else
                {
                    RenderNode(child, builder);
                }
            }

            if (closeTag != null)
            {
                if (node.IsInlineModifier)
                {
                    builder.Append(closeTag);
                }
                else
                {
                    builder.AppendLine(closeTag);
                }
            }
        }
示例#10
0
 public Markdown(string rawMarkdown)
 {
     _root = Parse(rawMarkdown);
 }