예제 #1
0
        public UtilsAdminApi()
            : base("/api/admin/utils")
        {
            this.RequiresHttpsOrXProto();
            this.RequiresAuthentication();
            this.RequiresClaims(new[] {SystemRoles.Administrators});

            Post["/slugs"] = parameters =>
            {
                var slugDto = this.Bind<SlugDto>();

                if (string.IsNullOrWhiteSpace(slugDto.Text))
                {
                    return global::System.Net.HttpStatusCode.BadRequest;
                }

                string slug = Snail.ToSlug(slugDto.Text);

                return new {Slug = slug};
            };

            Post["/markdown/render"] = parameters =>
            {
                string content = Request.Body.ReadAsString();

                if (string.IsNullOrEmpty(content))
                    return global::System.Net.HttpStatusCode.BadRequest;

                var parser = new MarkdownParser();
                var htmlRenderer = new MarkdownHtmlRenderer();

                string html = string.Empty;

                try
                {
                    Document document = parser.Parse(content);
                    html = htmlRenderer.Render(document);
                }
                catch (ParsingException x)
                {
                    html = string.Format(
                        "Markdown parsing error at {0} as block type {1}",
                        x.Position,
                        x.BuilderType);
                }
                catch (RenderingException renderingException)
                {
                    html = string.Format(
                        "Markdown rendering error with block {0} using {1} renderer",
                        renderingException.Block,
                        renderingException.Renderer);
                }

                return Response.AsText(html, "text/html");

            };
        }
예제 #2
0
        public void UsePreprocessors()
        {
            /* given */
            var builder = new StringBuilder();
            builder.AppendLine("paragraph is just text");
            builder.AppendLine("that can continue for");
            builder.AppendLine("multiple lines");
            string markdown = builder.ToString();

            var preprocessor = Substitute.For<IPreprocessor>();

            var parser = new MarkdownParser();
            parser.Pre.Insert(0, preprocessor);

            /* when */
            parser.Parse(markdown);

            /* then */
            preprocessor.Received().Process(Arg.Is(markdown));
        }
예제 #3
0
        public void MultipleParagraphs()
        {
            /* given */
            var builder = new StringBuilder();
            builder.AppendLine("paragraph is just text");
            builder.AppendLine("that can continue for");
            builder.AppendLine();
            builder.AppendLine("second paragraph");
            builder.AppendLine("multiple lines");
            string markdown = builder.ToString();

            var parser = new MarkdownParser();

            /* when */
            Document result = parser.Parse(markdown);

            /* then */
            result.Blocks.Should().HaveCount(2);
            result.Blocks.Should().ContainItemsAssignableTo<Paragraph>();
        }
예제 #4
0
        public void Paragraph()
        {
            /* given */
            var builder = new StringBuilder();
            builder.AppendLine("paragraph is just text");
            builder.AppendLine("that can continue for");
            builder.AppendLine("multiple lines");
            string markdown = builder.ToString();

            var parser = new MarkdownParser();

            /* when */
            Document result = parser.Parse(markdown);

            /* then */
            result.Blocks.Should().ContainSingle(block => block.GetType() == typeof (Paragraph));
            var paragraph = result.Blocks.Single() as Paragraph;
            paragraph.Start.ShouldBeEquivalentTo(0);
            paragraph.Spans.Should().HaveCount(5);
        }
예제 #5
0
        public void LinkDefinitions()
        {
            /* given */
            var builder = new StringBuilder();
            builder.AppendLine("[key 1]: url-1");
            builder.AppendLine("[key 2]: url-2");
            builder.AppendLine("[key 3]: url-3");
            string markdown = builder.ToString();

            var parser = new MarkdownParser();

            /* when */
            Document result = parser.Parse(markdown);

            /* then */
            var list = result.Blocks.Single() as LinkDefinitionList;
            for (int i = 0; i < list.Definitions.Count(); i++)
            {
                string expectedKey = string.Format("key {0}", i + 1);
                string expectedUrl = string.Format("url-{0}", i + 1);

                LinkDefinition definition = list.Definitions.ElementAt(i);

                definition.Key.ToString().ShouldBeEquivalentTo(expectedKey);
                definition.Url.ToString().ShouldBeEquivalentTo(expectedUrl);
            }
        }
        public void ParseMarkdownIntoHtml()
        {
            MarkdownParser parser = new MarkdownParser();

            Assert.IsTrue(parser.Parse("# Ceci est un test").Contains("Ceci est un test</h1>"));
        }
예제 #7
0
        public void OrdederedList()
        {
            /* given */
            var builder = new StringBuilder();
            builder.AppendLine("1. item 1");
            builder.AppendLine("2. item 2");
            builder.AppendLine("3. item 3");
            string markdown = builder.ToString();

            var parser = new MarkdownParser();

            /* when */
            Document result = parser.Parse(markdown);

            /* then */
            var list = result.Blocks.Single() as List;
            list.IsOrdered.ShouldBeEquivalentTo(true);
            for (int i = 0; i < list.Items.Count(); i++)
            {
                string expected = string.Format("item {0}", i + 1);
                Item item = list.Items.ElementAt(i);

                item.ToString().ShouldBeEquivalentTo(expected);
            }
        }
예제 #8
0
        public MarkdownDocument Parse(string text)
        {
            var document = MarkdownParser.Parse(text, _pipeline);

            return(document);
        }
예제 #9
0
        protected override async Task <IEnumerable <IDocument> > ExecuteInputAsync(IDocument input, IExecutionContext context)
        {
            context.LogDebug(
                "Processing Markdown {0} for {1}",
                string.IsNullOrEmpty(_sourceKey) ? string.Empty : ("in" + _sourceKey),
                input.ToSafeDisplayString());

            string content;

            if (string.IsNullOrEmpty(_sourceKey))
            {
                content = await input.GetContentStringAsync();
            }
            else if (input.ContainsKey(_sourceKey))
            {
                content = input.GetString(_sourceKey) ?? string.Empty;
            }
            else
            {
                // Don't do anything if the key doesn't exist
                return(input.Yield());
            }

            MarkdownPipeline pipeline = CreateMarkdownPipeline();

            string result;

            using (StringWriter writer = new StringWriter())
            {
                HtmlRenderer htmlRenderer = new HtmlRenderer(writer);
                pipeline.Setup(htmlRenderer);

                if (_prependLinkRoot && context.Settings.ContainsKey(Keys.LinkRoot))
                {
                    htmlRenderer.LinkRewriter = (link) =>
                    {
                        if (string.IsNullOrEmpty(link))
                        {
                            return(link);
                        }

                        if (link[0] == '/')
                        {
                            // root-based url, must be rewritten by prepending the LinkRoot setting value
                            // ex: '/virtual/directory' + '/relative/abs/link.html' => '/virtual/directory/relative/abs/link.html'
                            link = context.Settings[Keys.LinkRoot] + link;
                        }

                        return(link);
                    };
                }

                MarkdownDocument document = MarkdownParser.Parse(content, pipeline);
                htmlRenderer.Render(document);
                writer.Flush();
                result = writer.ToString();
            }

            if (_escapeAt)
            {
                result = EscapeAtRegex.Replace(result, "&#64;");
                result = result.Replace("\\@", "@");
            }

            return(string.IsNullOrEmpty(_sourceKey)
                ? input.Clone(await context.GetContentProviderAsync(result, MediaTypes.Html)).Yield()
                : input
                   .Clone(new MetadataItems
            {
                { string.IsNullOrEmpty(_destinationKey) ? _sourceKey : _destinationKey, result }
            })
                   .Yield());
        }
예제 #10
0
        public void ThrowParseErrorOnBuilderFailure()
        {
            /* given */
            var contentBuilder = new StringBuilder();
            contentBuilder.Append("1234567890");

            const int expectedPosition = 5;
            var parser = new MarkdownParser();
            parser.Builders.Insert(
                0,
                new ExceptionAtPositionBuilder(expectedPosition));
            
            /* when */
            var exception = Assert.Throws<ParsingException>(() =>
            {
                parser.Parse(contentBuilder.ToString());
            });

            exception.Position.ShouldBeEquivalentTo(expectedPosition);
            exception.BuilderType.ShouldBeEquivalentTo(typeof (ExceptionAtPositionBuilder));
            exception.InnerException.Should().BeOfType<ArgumentNullException>();
            exception.Content.ToString().ShouldBeEquivalentTo("67890");
        }
예제 #11
0
        public void SimpleMultipleParagraphs()
        {
            /* given */
            var builder = new StringBuilder();
            builder.AppendLine("p1");
            builder.AppendLine();
            builder.AppendLine("p2");
            string markdown = builder.ToString();

            var parser = new MarkdownParser();

            /* when */
            Document result = parser.Parse(markdown);

            /* then */
            result.Blocks.Should().HaveCount(2);
            result.Blocks.Should().ContainItemsAssignableTo<Paragraph>();
        }
예제 #12
0
        public void EmptyLine()
        {
            /* given */
            var builder = new StringBuilder();
            builder.AppendLine("paragraph is just text");
            builder.AppendLine("that can continue for");
            builder.AppendLine();
            builder.AppendLine("second paragraph");
            builder.AppendLine("multiple lines");
            string markdown = builder.ToString();

            var parser = new MarkdownParser(false);

            /* when */
            Document result = parser.Parse(markdown);

            /* then */
            result.Blocks.Should().HaveCount(3);
            var firstParagraph = result.Blocks.First() as Paragraph;
            firstParagraph.ToString().ShouldBeEquivalentTo("paragraph is just text\nthat can continue for\n");

            var emptyLine = result.Blocks.ElementAt(1) as EmptyLine;
            emptyLine.Should().NotBeNull();

            var secondParagraph = result.Blocks.Last() as Paragraph;
            secondParagraph.ToString().ShouldBeEquivalentTo("second paragraph\nmultiple lines\n");
        }
예제 #13
0
        public void ParagraphWithImage()
        {
            /* given */
            var contentBuilder = new StringBuilder();
            contentBuilder.Append("And images ![alt](http://image.jpg)");
            var parser = new MarkdownParser();

            /* when */
            var result = parser.Parse(contentBuilder.ToString());

            /* then */
            result.Blocks.Should().HaveCount(1);

            var paragaph = (Paragraph) result.Blocks.Single();
            paragaph.Spans.Should().HaveCount(2);
            paragaph.Spans.OfType<TextSpan>().Single().ToString().ShouldBeEquivalentTo("And images ");
            var image = paragaph.Spans.OfType<ImageSpan>().Single();
            image.Title.ToString().ShouldBeEquivalentTo("alt");
            image.Url.ToString().ShouldBeEquivalentTo("http://image.jpg");
        }
예제 #14
0
        public void MultipleParagraphsWithNewLines()
        {
            /* given */
            var builder = new StringBuilder();
            builder.Append(
                "Paragraphs should be separated by one empty line. Paragraph text is part of one \nparagraph as long as there's no empty lines.\n\nThis is a second paragraph which starts from new line and there's one empty line\nabove it.");

            var markdown = builder.ToString();
            var parser = new MarkdownParser();

            /* when */
            Document result = parser.Parse(markdown);

            /* then */
            result.Blocks.Should().HaveCount(2);
            result.Blocks.Should().ContainItemsAssignableTo<Paragraph>();
        }
예제 #15
0
        public void BugFixForNewLines()
        {
            /* given */
            var builder = new StringBuilder();
            builder.Append("#### Paragraphs\n");
            builder.Append("\n");
            builder.Append("Paragraphs are lines of text followed by empty line.\n");
            builder.Append("\n");
            builder.Append("Second paragraph with an inline link to this site [heikura.me][me]\n");
            string markdown = builder.ToString();

            var parser = new MarkdownParser();

            /* when */
            Document result = parser.Parse(markdown);

            /* then */
            result.Blocks.Should().HaveCount(3);
        }
예제 #16
0
 public static string CompileHTMLDoc(string filename, string css, string html)
 {
     return(GetHtmlHeader(filename) + css + htmlPostCss + MarkdownParser.Parse(html) + htmlFooter);
 }
 private string FormatMarkdown(string markdown) => FormatMarkdown(MarkdownParser.Parse(markdown));
예제 #18
0
 public static string FormatMarkdown(RenderContext context, string markdown) =>
 FormatMarkdownNodes(context, MarkdownParser.Parse(markdown), true);
예제 #19
0
        public void Empty()
        {
            /* given */
            var contentBuilder = new StringBuilder();
            var parser = new MarkdownParser();

            /* when */
            var result = parser.Parse(contentBuilder.ToString());

            /* then */
            result.Blocks.Should().HaveCount(0);
        }
예제 #20
0
        public void Codeblock()
        {
            /* given */
            var builder = new StringBuilder();
            builder.AppendLine("```");
            builder.AppendLine("public int X = 1;");
            builder.AppendLine("```");
            string markdown = builder.ToString();

            var parser = new MarkdownParser();

            /* when */
            Document result = parser.Parse(markdown);

            /* then */
            result.Blocks.Should().HaveCount(1);
            result.Blocks.Should().ContainSingle(block => block.GetType() == typeof (Codeblock));
        }
예제 #21
0
        public void CodeblocskWithSyntaxIdentifier()
        {
            /* given */
            var builder = new StringBuilder();
            builder.AppendLine("```cs");
            builder.AppendLine("public int X = 1;");
            builder.AppendLine("```");
            builder.AppendLine("```js");
            builder.AppendLine("int X = 1;");
            builder.AppendLine("```");
            string markdown = builder.ToString();

            var parser = new MarkdownParser();

            /* when */
            Document result = parser.Parse(markdown);

            /* then */
            result.Blocks.Count().ShouldBeEquivalentTo(2);
            result.Blocks.Cast<Codeblock>().First().Syntax.ToString().ShouldBeEquivalentTo("cs");
            result.Blocks.Cast<Codeblock>().Last().Syntax.ToString().ShouldBeEquivalentTo("js");
        }
예제 #22
0
        public void CodeblocsWithSyntaxIdentifierAndParagraphBetween()
        {
            /* given */
            var builder = new StringBuilder();
            builder.AppendLine("```cs");
            builder.AppendLine("public int X = 1;");
            builder.AppendLine("```");
            builder.AppendLine("Some text here to separate the two");
            builder.AppendLine("```js");
            builder.AppendLine("public int X = 1;");
            builder.AppendLine("```");
            string markdown = builder.ToString();

            var parser = new MarkdownParser();

            /* when */
            Document result = parser.Parse(markdown);

            /* then */
            result.Blocks.Count().ShouldBeEquivalentTo(3);
            result.Blocks.ElementAt(0).As<Codeblock>().Syntax.ToString().ShouldBeEquivalentTo("cs");
            result.Blocks.ElementAt(1).As<Paragraph>().ToString().ShouldBeEquivalentTo("\nSome text here to separate the two\n");
            result.Blocks.ElementAt(2).As<Codeblock>().Syntax.ToString().ShouldBeEquivalentTo("js");
        }
예제 #23
0
        public void RenderShouldReturnSame_WhenInputWithoutTags()
        {
            var input = "Input string without tags";

            GetTagsSequence(parser.Parse(input)).Should().BeEquivalentTo(Tag.NoFormatting);
        }
예제 #24
0
        public void SetextHeadings()
        {
            /* given */
            var builder = new StringBuilder();
            builder.AppendLine("Setext 1");
            builder.AppendLine("========");
            builder.AppendLine("Setext 2");
            builder.AppendLine("--------");
            string markdown = builder.ToString();

            var parser = new MarkdownParser();

            /* when */
            Document result = parser.Parse(markdown);

            /* then */
            result.Blocks.Should().HaveCount(2);

            var headingOne = result.Blocks.First() as Heading;
            headingOne.Level.ShouldBeEquivalentTo(1);
            headingOne.ToString().ShouldBeEquivalentTo("Setext 1");

            var headingTwo = result.Blocks.Last() as Heading;
            headingTwo.Level.ShouldBeEquivalentTo(2);
            headingTwo.ToString().ShouldBeEquivalentTo("Setext 2");
        }
예제 #25
0
 protected override void When()
 {
     _result = _sut.Parse(_markdown);
 }
예제 #26
0
        public void Headings()
        {
            /* given */
            var builder = new StringBuilder();
            builder.AppendLine("# Heading 1");
            builder.AppendLine("## Heading 2");
            builder.AppendLine("### Heading 3");
            builder.AppendLine("#### Heading 4");
            builder.AppendLine("##### Heading 5");
            builder.AppendLine("###### Heading 6");
            string markdown = builder.ToString();

            var parser = new MarkdownParser();

            /* when */
            Document result = parser.Parse(markdown);

            /* then */
            for (int i = 0; i < result.Blocks.Count(); i++)
            {
                string expected = string.Format("Heading {0}", i + 1);
                var heading = result.Blocks.ElementAt(i) as Heading;

                heading.Level.ShouldBeEquivalentTo(i + 1);
                heading.ToString().ShouldBeEquivalentTo(expected);
            }
        }
예제 #27
0
        private static BlogPostDto ToDto(BlogPost blogPost)
        {
            string html = string.Empty;

            if (!string.IsNullOrWhiteSpace(blogPost.Content))
            {
                var md = new MarkdownParser();
                var renderer = new MarkdownHtmlRenderer();

                try
                {
                    Document document = md.Parse(blogPost.Content);
                    html = renderer.Render(document);
                }
                catch (ParsingException x)
                {
                    html = string.Format(
                        "Markdown parsing error at {0} as block type {1}",
                        x.Position,
                        x.BuilderType);
                }
                catch (RenderingException renderingException)
                {
                    html = string.Format(
                        "Markdown rendering error with block {0} using {1} renderer",
                        renderingException.Block,
                        renderingException.Renderer);
                }
            }

            return new BlogPostDto
            {
                Content = html,
                Author = blogPost.Author,
                Created = blogPost.Created,
                PublishedOn = blogPost.PublishedOn,
                Title = blogPost.Title,
                Slug = blogPost.Slug,
                Id = Id.WithoutCollection(blogPost.Id),
                Tags = blogPost.Tags ?? new Collection<string>()
            };
        }
예제 #28
0
        /// <inheritdoc />
        public IEnumerable <IDocument> Execute(IReadOnlyList <IDocument> inputs, IExecutionContext context)
        {
            return(inputs.AsParallel().Select(context, input =>
            {
                Trace.Verbose(
                    "Processing Markdown {0} for {1}",
                    string.IsNullOrEmpty(_sourceKey) ? string.Empty : ("in" + _sourceKey),
                    input.SourceString());

                string result;

                IExecutionCache executionCache = context.ExecutionCache;

                if (!executionCache.TryGetValue <string>(input, _sourceKey, out result))
                {
                    string content;
                    if (string.IsNullOrEmpty(_sourceKey))
                    {
                        content = input.Content;
                    }
                    else if (input.ContainsKey(_sourceKey))
                    {
                        content = input.String(_sourceKey) ?? string.Empty;
                    }
                    else
                    {
                        // Don't do anything if the key doesn't exist
                        return input;
                    }

                    MarkdownPipeline pipeline = CreatePipeline();

                    using (StringWriter writer = new StringWriter())
                    {
                        HtmlRenderer htmlRenderer = new HtmlRenderer(writer);
                        pipeline.Setup(htmlRenderer);

                        if (_prependLinkRoot && context.Settings.ContainsKey(Keys.LinkRoot))
                        {
                            htmlRenderer.LinkRewriter = (link) =>
                            {
                                if (link == null || link.Length == 0)
                                {
                                    return link;
                                }

                                if (link[0] == '/')
                                {
                                    // root-based url, must be rewritten by prepending the LinkRoot setting value
                                    // ex: '/virtual/directory' + '/relative/abs/link.html' => '/virtual/directory/relative/abs/link.html'
                                    link = context.Settings[Keys.LinkRoot] + link;
                                }

                                return link;
                            };
                        }

                        MarkdownDocument document = MarkdownParser.Parse(content, pipeline);
                        htmlRenderer.Render(document);
                        writer.Flush();
                        result = writer.ToString();
                    }

                    if (_escapeAt)
                    {
                        result = EscapeAtRegex.Replace(result, "&#64;");
                        result = result.Replace("\\@", "@");
                    }

                    executionCache.Set(input, _sourceKey, result);
                }

                return string.IsNullOrEmpty(_sourceKey)
                    ? context.GetDocument(input, context.GetContentStream(result))
                    : context.GetDocument(input, new MetadataItems
                {
                    { string.IsNullOrEmpty(_destinationKey) ? _sourceKey : _destinationKey, result }
                });
            }));
        }