예제 #1
0
        private string GetString(TextElement[] texts)
        {
            StringBuilder builder = new StringBuilder();

            foreach (TextElement i in texts)
            {
                if (i is TextSpan)
                {
                    TextSpan s = (TextSpan)i;

                    builder.Append(Escape(s.Text));
                }
                else if (i is CodeSpan)
                {
                    CodeSpan s = (CodeSpan)i;

                    builder.Append(Escape(s.Text));
                }
                else if (i is HyperlinkSpan)
                {
                    HyperlinkSpan s = (HyperlinkSpan)i;
                    builder.Append(Escape(s.Text));
                }
            }
            return(builder.ToString());
        }
예제 #2
0
        public void ParsesDocumentWithMultipleNodes()
        {
            string documentText =
                string.Format(
                    @"
# {0}

{2}

```
{1}
```

## {0}
{2} [{3}]({4})
", headingText, codeBlockText, paragraphText, hyperlinkText, hyperlinkUri);

            MarkdownParser markdownParser = new MarkdownParser();
            DocumentNode   documentNode   =
                markdownParser.ParseString(
                    documentText);

            HeadingNode headingNode =
                this.AssertNodeType <HeadingNode>(
                    documentNode.Children.ElementAtOrDefault(0),
                    MarkdownNodeType.Heading);

            Assert.Equal(headingText, headingNode.Text);
            Assert.Equal(1, headingNode.HeadingLevel);

            CodeBlockNode codeBlockNode =
                this.AssertNodeType <CodeBlockNode>(
                    documentNode.Children.ElementAtOrDefault(2),
                    MarkdownNodeType.CodeBlock);

            Assert.Equal(codeBlockText, codeBlockNode.Text);

            headingNode =
                this.AssertNodeType <HeadingNode>(
                    documentNode.Children.ElementAtOrDefault(3),
                    MarkdownNodeType.Heading);

            Assert.Equal(headingText, headingNode.Text);
            Assert.Equal(2, headingNode.HeadingLevel);

            ParagraphNode paragraphNode =
                this.AssertNodeType <ParagraphNode>(
                    documentNode.Children.ElementAtOrDefault(4),
                    MarkdownNodeType.Paragraph);

            Assert.Equal(paragraphText.Replace("\r\n", " "), paragraphNode.Spans.First().Text);

            HyperlinkSpan hyperlinkSpan =
                Assert.IsType <HyperlinkSpan>(
                    paragraphNode.Spans.ElementAt(1));

            Assert.Equal(hyperlinkText, hyperlinkSpan.Text);
            Assert.Equal(hyperlinkUri, hyperlinkSpan.Uri);
        }
예제 #3
0
        public void ParsesHyperlinkWithoutLink()
        {
            ParagraphNode paragraphNode =
                this.ParseAndGetExpectedChild <ParagraphNode>(
                    string.Format(
                        "[{0}]()",
                        hyperlinkText),
                    MarkdownNodeType.Paragraph);

            HyperlinkSpan hyperlinkSpan =
                Assert.IsType <HyperlinkSpan>(
                    paragraphNode.Spans.FirstOrDefault());

            Assert.Equal(hyperlinkText, hyperlinkSpan.Text);
            Assert.Equal("", hyperlinkSpan.Uri);
        }
예제 #4
0
        private string GetTextFromParagraphSpans(IEnumerable <ParagraphSpan> spans)
        {
            // in preserve formatting there is only one span all the time
            if (spans.Count() == 1)
            {
                var textSpan = spans.First() as TextSpan;
                if (textSpan.ParserMode == ParserMode.FormattingPreserve)
                {
                    return(textSpan.Text);
                }
            }

            StringBuilder sb    = new StringBuilder();
            bool          first = true;
            bool          previousIsHyperLink = false;

            foreach (var paragraphSpan in spans)
            {
                // TODO: make it handle hyperlinks, codesnippets, etc more wisely

                HyperlinkSpan hyperlink = paragraphSpan as HyperlinkSpan;
                if (!first && hyperlink != null)
                {
                    sb.Append(" ");
                }
                else if (previousIsHyperLink)
                {
                    sb.Append(" ");
                }

                sb.Append(paragraphSpan.Text);
                if (hyperlink != null)
                {
                    if (!string.IsNullOrWhiteSpace(hyperlink.Uri))
                    {
                        sb.AppendFormat(" ({0})", hyperlink.Uri);
                    }
                    else
                    {
                        previousIsHyperLink = paragraphSpan is HyperlinkSpan;
                    }
                }

                first = false;
            }
            return(sb.ToString());
        }
예제 #5
0
파일: TextParser.cs 프로젝트: ptrepos/mdoc
        private void Parse(Status status)
        {
            StringBuilder builder = new StringBuilder();

            while (index < text.Length)
            {
                switch (text[index])
                {
                case '*':
                    if (status == Status.STRONG)
                    {
                        if (Match(text, index + 1, '*'))
                        {
                            if (builder.Length > 0)
                            {
                                elems.Add(new TextSpan(builder.ToString()));
                                builder.Clear();
                            }

                            elems.Add(new StrongCloseTag());
                            index += 2;
                            return;
                        }
                    }
                    if (status == Status.EMPHASIS)
                    {
                        if (builder.Length > 0)
                        {
                            elems.Add(new TextSpan(builder.ToString()));
                            builder.Clear();
                        }

                        elems.Add(new EmphasisCloseTag());
                        index += 1;
                        return;
                    }

                    if (Match(text, index + 1, '*'))
                    {
                        // **
                        if (builder.Length > 0)
                        {
                            elems.Add(new TextSpan(builder.ToString()));
                            builder.Clear();
                        }

                        index += 2;

                        elems.Add(new StrongOpenTag());

                        Parse(Status.STRONG);
                    }
                    else
                    {
                        // *
                        if (builder.Length > 0)
                        {
                            elems.Add(new TextSpan(builder.ToString()));
                            builder.Clear();
                        }

                        index += 1;

                        elems.Add(new EmphasisOpenTag());

                        Parse(Status.EMPHASIS);
                    }
                    break;

                case '`':
                    if (builder.Length > 0)
                    {
                        elems.Add(new TextSpan(builder.ToString()));
                        builder.Clear();
                    }

                    // `XXXXXXXXXXXXXXXXXXX`
                    CodeSpan codeSpan = ParseCode(text, ref index);
                    if (codeSpan != null)
                    {
                        elems.Add(codeSpan);
                    }

                    break;

                case '\\':
                    if (index + 1 < text.Length)
                    {
                        // \?
                        builder.Append(text[index + 1]);
                        index += 2;
                    }
                    else
                    {
                        // \マークは消える
                        index += 1;
                    }
                    break;

                case '[':
                    if (Match(text, index + 1, '['))
                    {
                        // [[
                        if (builder.Length > 0)
                        {
                            elems.Add(new TextSpan(builder.ToString()));
                            builder.Clear();
                        }

                        HyperlinkSpan tag = ParseUrlHyperlink(text, ref index);
                        if (tag != null)
                        {
                            elems.Add(tag);
                        }
                        continue;
                    }
                    else
                    {
                        // [
                        if (builder.Length > 0)
                        {
                            elems.Add(new TextSpan(builder.ToString()));
                            builder.Clear();
                        }

                        HyperlinkSpan tag = ParseHyperlink(text, ref index);
                        if (tag != null)
                        {
                            elems.Add(tag);
                        }
                    }
                    break;

                case '!':
                    if (Match(text, index + 1, '['))
                    {
                        // ![
                        if (builder.Length > 0)
                        {
                            elems.Add(new TextSpan(builder.ToString()));
                            builder.Clear();
                        }

                        ImageSpan tag = ParseImage(text, ref index);
                        if (tag != null)
                        {
                            elems.Add(tag);
                        }
                        continue;
                    }
                    break;

                case '<':
                    string element;
                    Dictionary <string, string> attrs;
                    bool closed;

                    if (ParseHtmlTagClose(text, ref index, out element))
                    {
                        if (builder.Length > 0)
                        {
                            elems.Add(new TextSpan(builder.ToString()));
                            builder.Clear();
                        }

                        if (status == Status.HTML_EM)
                        {
                            if (element.ToLower() == "em")
                            {
                                elems.Add(new EmphasisCloseTag());
                                return;
                            }
                        }
                        else if (status == Status.HTML_STRONG)
                        {
                            if (element.ToLower() == "strong")
                            {
                                elems.Add(new StrongCloseTag());
                                return;
                            }
                        }
                        else if (status == Status.HTML_DEL)
                        {
                            if (element.ToLower() == "del")
                            {
                                elems.Add(new StrikethroughCloseTag());
                                return;
                            }
                        }
                        else if (status == Status.HTML_SUP)
                        {
                            if (element.ToLower() == "sup")
                            {
                                elems.Add(new SuperscriptCloseTag());
                                return;
                            }
                        }
                        else if (status == Status.HTML_SUB)
                        {
                            if (element.ToLower() == "sub")
                            {
                                elems.Add(new SubscriptCloseTag());
                                return;
                            }
                        }
                        else if (status == Status.HTML_SMALL)
                        {
                            if (element.ToLower() == "small")
                            {
                                elems.Add(new SmallCloseTag());
                                return;
                            }
                        }

                        throw new MdocParseException("予期せぬHTMLタグを検出しました。", line);
                    }
                    else if (ParseHtmlTagOpen(text, ref index, out closed, out element, out attrs))
                    {
                        if (builder.Length > 0)
                        {
                            elems.Add(new TextSpan(builder.ToString()));
                            builder.Clear();
                        }
                        element = element.ToLower();
                        if (element == "em")
                        {
                            elems.Add(new EmphasisOpenTag());

                            if (closed)
                            {
                                elems.Add(new EmphasisCloseTag());
                            }
                            else
                            {
                                Parse(Status.HTML_EM);
                            }
                        }
                        else if (element == "strong")
                        {
                            elems.Add(new StrongOpenTag());

                            if (closed)
                            {
                                elems.Add(new StrongCloseTag());
                            }
                            else
                            {
                                Parse(Status.HTML_STRONG);
                            }
                        }
                        else if (element == "del")
                        {
                            elems.Add(new StrikethroughOpenTag());

                            if (closed)
                            {
                                elems.Add(new StrikethroughCloseTag());
                            }
                            else
                            {
                                Parse(Status.HTML_DEL);
                            }
                        }
                        else if (element == "sup")
                        {
                            elems.Add(new SuperscriptOpenTag());

                            if (closed)
                            {
                                elems.Add(new SuperscriptCloseTag());
                            }
                            else
                            {
                                Parse(Status.HTML_SUP);
                            }
                        }
                        else if (element == "sub")
                        {
                            elems.Add(new SubscriptOpenTag());

                            if (closed)
                            {
                                elems.Add(new SubscriptCloseTag());
                            }
                            else
                            {
                                Parse(Status.HTML_SUB);
                            }
                        }
                        else if (element == "small")
                        {
                            elems.Add(new SmallOpenTag());

                            if (closed)
                            {
                                elems.Add(new SmallCloseTag());
                            }
                            else
                            {
                                Parse(Status.HTML_SMALL);
                            }
                        }
                        else
                        {
                            throw new MdocParseException("予期せぬHTMLタグを検出しました。", line);
                        }
                    }
                    break;

                default:
                    builder.Append(text[index]);
                    index += 1;
                    break;
                }
            }

            if (builder.Length > 0)
            {
                elems.Add(new TextSpan(builder.ToString()));
                builder.Clear();
            }

            if (status == Status.EMPHASIS)
            {
                throw new MdocParseException(MessageResource.EmphasisError, line);
            }
            if (status == Status.STRONG)
            {
                throw new MdocParseException(MessageResource.BoldError, line);
            }
            if (status == Status.HTML_DEL)
            {
                throw new MdocParseException(MessageResource.HtmlDelError, line);
            }
            if (status == Status.HTML_EM)
            {
                throw new MdocParseException(MessageResource.HtmlEmError, line);
            }
            if (status == Status.HTML_STRONG)
            {
                throw new MdocParseException(MessageResource.HtmlStrongError, line);
            }
            if (status == Status.HTML_SUP)
            {
                throw new MdocParseException(MessageResource.HtmlSupError, line);
            }
            if (status == Status.HTML_SUB)
            {
                throw new MdocParseException(MessageResource.HtmlSubError, line);
            }
            if (status == Status.HTML_SMALL)
            {
                throw new MdocParseException(MessageResource.HtmlSmallError, line);
            }
        }
예제 #6
0
        private void WriteText(TextWriter writer, TextElement[] elems)
        {
            foreach (TextElement i in elems)
            {
                if (i is TextSpan)
                {
                    TextSpan s = (TextSpan)i;

                    writer.Write(Escape(s.Text));
                }
                else if (i is CodeSpan)
                {
                    CodeSpan s = (CodeSpan)i;

                    writer.Write(Escape(s.Text));
                }
                else if (i is EmphasisOpenTag)
                {
                    writer.Write("<em>");
                }
                else if (i is EmphasisCloseTag)
                {
                    writer.Write("</em>");
                }
                else if (i is StrongOpenTag)
                {
                    writer.Write("<strong>");
                }
                else if (i is StrongCloseTag)
                {
                    writer.Write("</strong>");
                }
                else if (i is StrikethroughOpenTag)
                {
                    writer.Write("<strike>");
                }
                else if (i is StrikethroughCloseTag)
                {
                    writer.Write("</strike>");
                }
                else if (i is SuperscriptOpenTag)
                {
                    writer.Write("<sup>");
                }
                else if (i is SuperscriptCloseTag)
                {
                    writer.Write("</sup>");
                }
                else if (i is SubscriptOpenTag)
                {
                    writer.Write("<sub>");
                }
                else if (i is SubscriptCloseTag)
                {
                    writer.Write("</sub>");
                }
                else if (i is SmallOpenTag)
                {
                    writer.Write("<small>");
                }
                else if (i is SmallCloseTag)
                {
                    writer.Write("</small>");
                }
                else if (i is HyperlinkSpan)
                {
                    HyperlinkSpan s = (HyperlinkSpan)i;
                    writer.Write("<a href=\"{1}\">{0}</a>", Escape(s.Text), Escape(s.Href));
                }
                else if (i is ImageSpan)
                {
                    ImageSpan s = (ImageSpan)i;
                    writer.Write("<img src=\"{1}\" alt=\"{0}\"/>", Escape(s.Text), Escape(s.Source));
                }
            }
        }