Пример #1
0
        public string Render(SourceFile sourceFile, string template, object data)
        {
            var pipeline = new MarkdownPipelineBuilder()
                .UseAdvancedExtensions()
                .Build();

            var result = Markdown.ToHtml(template, pipeline);

            return result.Trim();
        }
Пример #2
0
        public Browser(string file)
        {
            var builder = new MarkdownPipelineBuilder()
                .UsePragmaLines()
                .UseAdvancedExtensions();

            _pipeline = builder.Build();
            _zoomFactor = GetZoomFactor();
            _file = file;
            _htmlTemplate = GetHtmlTemplate();
            _currentViewLine = -1;

            InitBrowser();
        }
        public override MarkdownPipeline GetPipeline()
        {
            var pipelineBuilder = new MarkdownPipelineBuilder();

            if (PipeTables) pipelineBuilder = pipelineBuilder.UsePipeTables();
            if (GridTables) pipelineBuilder = pipelineBuilder.UseGridTables();
            if (ExtraEmphasis) pipelineBuilder = pipelineBuilder.UseEmphasisExtras();
            if (DefinitionLists) pipelineBuilder = pipelineBuilder.UseDefinitionLists();
            if (Footnotes) pipelineBuilder = pipelineBuilder.UseFootnotes();
            if (TaskLists) pipelineBuilder = pipelineBuilder.UseTaskLists();
            if (ExtraBulletLists) pipelineBuilder = pipelineBuilder.UseListExtras();
            if (Abbreviations) pipelineBuilder = pipelineBuilder.UseAbbreviations();
            if (Emoji) pipelineBuilder = pipelineBuilder.UseEmojiAndSmiley();

            return pipelineBuilder.Build();
        }
 public void CodeSampleWorks() {
     var codebase = Assembly.GetExecutingAssembly().GetName().CodeBase;
     var directory = Path.GetDirectoryName(codebase);
     if (directory == null) {
         throw new NullReferenceException("appPath came back null.");
     }
     var appPath = new Uri(directory).LocalPath;
     var folder = Path.Combine(appPath, "Example");
     var inputMarkdown = Path.Combine(folder, "README.md");
     var referenceFile = Path.Combine(folder, "expected.html");
     var expectedHtml = File.ReadAllText(referenceFile);
     var markdown = File.ReadAllText(inputMarkdown);
     var pipeline = new MarkdownPipelineBuilder()
         .UseAdvancedExtensions()
         .UseSyntaxHighlighting()
         .Build();
     var html = Markdown.ToHtml(markdown, pipeline);
     var actualHtml = File.ReadAllText(Path.Combine(folder, "_template.html"))
         .Replace("{{{this}}}", html);
     actualHtml = actualHtml.Replace("\r\n", "\n").Replace("\n", "\r\n");
     File.WriteAllText(Path.Combine(folder, "actual.html"), actualHtml);
     Assert.Equal(expectedHtml, actualHtml);
 }
Пример #5
0
 public void Setup(MarkdownPipelineBuilder pipeline)
 {
     _pipeline = pipeline;
     _pipeline.DocumentProcessed += PipelineOnDocumentProcessed;
 }
Пример #6
0
 public static MarkdownPipelineBuilder UseQuoteSectionNote(this MarkdownPipelineBuilder pipeline, MarkdownContext context)
 {
     pipeline.Extensions.Insert(0, new QuoteSectionNoteExtension(context));
     return(pipeline);
 }
Пример #7
0
        public static string ToPlainText(this JournalPost post)
        {
            var pipeline = new MarkdownPipelineBuilder().Build();

            return(Markdown.ToPlainText(post.Content, pipeline));
        }
 /// <summary>
 /// Adds a new <see cref="SyntaxHighlighterMarkdownExtension"/> to the specified Markdig <paramref name="pipeline"/>.
 /// </summary>
 /// <param name="pipeline">The pipeline.</param>
 /// <returns>The pipeline.</returns>
 public static MarkdownPipelineBuilder UseSyntaxHighlighter(this MarkdownPipelineBuilder pipeline)
 {
     pipeline.Extensions.Add(new SyntaxHighlighterMarkdownExtension());
     return(pipeline);
 }
Пример #9
0
 public void Setup(MarkdownPipelineBuilder pipeline)
 {
     pipeline.BlockParsers.AddIfNotAlready <CodeSnippetParser>();
 }
Пример #10
0
 public void Setup(MarkdownPipelineBuilder pipeline) =>
 pipeline.BlockParsers.Insert(0, new BlockParser());
Пример #11
0
 public static MarkdownPipelineBuilder UseYamlHeader(this MarkdownPipelineBuilder pipeline)
 {
     pipeline.Extensions.Insert(0, new YamlHeaderExtension());
     return(pipeline);
 }
Пример #12
0
 public void Setup(MarkdownPipelineBuilder pipeline)
 {
     pipeline.InlineParsers.AddIfNotAlready <VariableInlineParser>();
 }
Пример #13
0
 public static MarkdownPipelineBuilder UseMonikerRange(this MarkdownPipelineBuilder pipeline, MarkdownContext context)
 {
     pipeline.Extensions.AddIfNotAlready(new MonikerRangeExtension(context));
     return(pipeline);
 }
Пример #14
0
 public static MarkdownPipelineBuilder UseHeadingIdRewriter(this MarkdownPipelineBuilder pipeline)
 {
     pipeline.Extensions.Add(new HeadingIdExtension());
     return(pipeline);
 }
Пример #15
0
 public static MarkdownPipelineBuilder UseTabGroup(this MarkdownPipelineBuilder pipeline, MarkdownContext context)
 {
     pipeline.Extensions.Add(new TabGroupExtension(context));
     return(pipeline);
 }
Пример #16
0
 /// <summary>
 /// This extension removes all the block parser except paragragh. Please use this extension in the last.
 /// </summary>
 public static MarkdownPipelineBuilder UseInlineOnly(this MarkdownPipelineBuilder pipeline)
 {
     pipeline.Extensions.Add(new InlineOnlyExtentsion());
     return(pipeline);
 }
Пример #17
0
 public static MarkdownPipelineBuilder UseNestedColumn(this MarkdownPipelineBuilder pipeline, MarkdownContext context)
 {
     pipeline.Extensions.AddIfNotAlready(new NestedColumnExtension(context));
     return(pipeline);
 }
Пример #18
0
 public static MarkdownPipelineBuilder UseMonikerRange(this MarkdownPipelineBuilder pipeline)
 {
     pipeline.Extensions.AddIfNotAlready <MonikerRangeExtension>();
     return(pipeline);
 }
Пример #19
0
 public static MarkdownPipelineBuilder UseLineNumber(this MarkdownPipelineBuilder pipeline, Func <object, string> getFilePath = null)
 {
     pipeline.Extensions.Add(new LineNumberExtension(getFilePath));
     return(pipeline);
 }
Пример #20
0
        public static MarkdownPipelineBuilder RemoveUnusedExtensions(this MarkdownPipelineBuilder pipeline)
        {
            pipeline.Extensions.RemoveAll(extension => extension is CustomContainerExtension);

            return(pipeline);
        }
Пример #21
0
 public static MarkdownPipelineBuilder UseIncludeFile(this MarkdownPipelineBuilder pipeline, MarkdownContext context)
 {
     pipeline.Extensions.Insert(0, new InclusionExtension(context));
     return(pipeline);
 }
Пример #22
0
        /// <summary>
        /// Constructs a DocComment instance from the documentation comments
        /// associated with a source code element.
        /// </summary>
        /// <param name="docComments">The doc comments from the source code</param>
        /// <param name="name">The name of the element</param>
        /// <param name="deprecated">Flag indicating whether or not the element had a Deprecated attribute</param>
        /// <param name="replacement">The name of the replacement element for deprecated elements, if given</param>
        public DocComment(IEnumerable <string> docComments, string name, bool deprecated, string replacement)
        {
            string GetHeadingText(HeadingBlock heading)
            {
                var sb = new StringBuilder();

                foreach (var item in heading.Inline)
                {
                    sb.Append(item.ToString());
                }
                return(sb.ToString());
            }

            string GetParagraphText(LeafBlock leaf)
            {
                var sb = new StringBuilder();

                foreach (var item in leaf.Inline)
                {
                    sb.Append(item.ToString());
                }
                return(sb.ToString());
            }

            string ToMarkdown(IEnumerable <Block> blocks)
            {
                var writer   = new StringWriter();
                var renderer = new NormalizeRenderer(writer);
                var pipeline = new MarkdownPipelineBuilder().Build();

                pipeline.Setup(renderer);
                foreach (var block in blocks)
                {
                    renderer.Render(block);
                }
                // We convert \n to \r because the YAML serialization will eventually
                // output \n\n for \n, but \r\n for \r.
                return(writer.ToString().TrimEnd().Replace('\n', '\r'));
            }

            List <ValueTuple <string, List <Block> > > BreakIntoSections(IEnumerable <Block> blocks, int level)
            {
                var key    = "";
                var accum  = new List <Block>();
                var result = new List <ValueTuple <string, List <Block> > >();

                foreach (var block in blocks)
                {
                    if (block is HeadingBlock heading)
                    {
                        if (heading.Level == level)
                        {
                            if (accum.Count > 0)
                            {
                                result.Add(new ValueTuple <string, List <Block> >(key, accum));
                                accum = new List <Block>();
                            }
                            key = GetHeadingText(heading);
                        }
                        else
                        {
                            accum.Add(block);
                        }
                    }
                    else
                    {
                        accum.Add(block);
                    }
                }

                if (accum.Count > 0)
                {
                    result.Add(new ValueTuple <string, List <Block> >(key, accum));
                }

                return(result);
            }

            void ParseListSection(IEnumerable <Block> blocks, List <string> accum, bool lowerCase)
            {
                foreach (var block in blocks)
                {
                    if (block is ListBlock list)
                    {
                        foreach (var sub in block.Descendants())
                        {
                            if (sub is ListItemBlock item)
                            {
                                // Some special treatment for funky doc comments in some of the Canon
                                if (item.Count == 1 && item.LastChild is LeafBlock leaf && leaf.Inline != null &&
                                    leaf.Inline.FirstChild is LiteralInline literal)
                                {
                                    var itemText = lowerCase ? GetParagraphText(leaf).ToLowerInvariant() : GetParagraphText(leaf);
                                    if (itemText.StartsWith("@\"") && itemText.EndsWith("\""))
                                    {
                                        itemText = itemText.Substring(2, itemText.Length - 3);
                                    }
                                    literal.Content = new Markdig.Helpers.StringSlice(itemText.ToLowerInvariant());
                                }
                                accum.Add(ToMarkdown(new Block[] { item }));
                            }
                        }
                    }
                }
            }

            void ParseMapSection(IEnumerable <Block> blocks, Dictionary <string, string> accum)
            {
                var subsections = BreakIntoSections(blocks, 2);

                foreach ((var key, var subs) in subsections)
                {
                    // TODO: when we add the ability to flag warnings from the doc comment builder,
                    // we should check here for duplicate keys and generate a warning if appropriate.
                    accum[key] = ToMarkdown(subs);
                }
            }

            // First element is not matching, second is matching
            (List <Block>, List <Block>) PartitionNestedSection(IEnumerable <Block> blocks, int level, string name)
            {
                var inMatch = false;
                var result  = (new List <Block>(), new List <Block>());

                foreach (var block in blocks)
                {
                    var skip = false;
                    if ((block is HeadingBlock heading) && (heading.Level == level))
                    {
                        inMatch = GetHeadingText(heading).Equals(name);
                        skip    = true;
                    }
                    if (inMatch)
                    {
                        if (!skip)
                        {
                            result.Item2.Add(block);
                        }
                    }
                    else
                    {
                        result.Item1.Add(block);
                    }
                }

                return(result);
            }

            // Initialize to safe empty values
            this.Summary        = "";
            this.Description    = "";
            this.ShortSummary   = "";
            this.Documentation  = "";
            this.Input          = new Dictionary <string, string>();
            this.Output         = "";
            this.TypeParameters = new Dictionary <string, string>();
            this.Example        = "";
            this.Remarks        = "";
            this.SeeAlso        = new List <string>();
            this.References     = "";

            var deprecationSummary = String.IsNullOrWhiteSpace(replacement)
                                    ? DiagnosticItem.Message(WarningCode.DeprecationWithoutRedirect, new string[] { name })
                                    : DiagnosticItem.Message(WarningCode.DeprecationWithRedirect, new string[] { name, "@\"" + replacement.ToLowerInvariant() + "\"" });
            var deprecationDetails = "";

            var text = String.Join("\n", docComments);

            // Only parse if there are comments to parse
            if (!string.IsNullOrWhiteSpace(text))
            {
                var          doc                = Markdown.Parse(text);
                var          sections           = BreakIntoSections(doc, 1);
                List <Block> summarySection     = new List <Block>();
                List <Block> descriptionSection = new List <Block>();

                foreach ((var tag, var section) in sections)
                {
                    switch (tag)
                    {
                    case "Summary":
                        this.Summary = ToMarkdown(section);
                        summarySection.AddRange(section);
                        // For now, the short hover information gets the first paragraph of the summary.
                        this.ShortSummary = ToMarkdown(section.GetRange(0, 1));
                        break;

                    case "Deprecated":
                        if (String.IsNullOrWhiteSpace(name))
                        {
                            deprecationSummary = ToMarkdown(section.GetRange(0, 1));
                            if (section.Count > 1)
                            {
                                deprecationDetails = ToMarkdown(section.GetRange(1, section.Count - 1));
                            }
                        }
                        else
                        {
                            deprecationDetails = ToMarkdown(section);
                        }
                        deprecated = true;
                        break;

                    case "Description":
                        this.Description   = ToMarkdown(section);
                        descriptionSection = section;
                        break;

                    case "Input":
                        ParseMapSection(section, this.Input);
                        break;

                    case "Output":
                        this.Output = ToMarkdown(section);
                        break;

                    case "Type Parameters":
                        ParseMapSection(section, this.TypeParameters);
                        break;

                    case "Example":
                        this.Example = ToMarkdown(section);
                        break;

                    case "Remarks":
                        (var remarks, var examples) = PartitionNestedSection(section, 2, "Example");
                        if ((examples.Count > 0) && (this.Example == ""))
                        {
                            this.Example = ToMarkdown(examples);
                        }
                        this.Remarks = ToMarkdown(remarks);
                        break;

                    case "See Also":
                        // seeAlso is a list of UIDs, which are all lower case,
                        // so pass true to lowercase all strings found in this section
                        ParseListSection(section, this.SeeAlso, true);
                        break;

                    case "References":
                        this.References = ToMarkdown(section);
                        break;

                    default:
                        // TODO: add diagnostic warning about unknown tag
                        break;
                    }
                }


                this.Documentation = ToMarkdown(summarySection.Concat(descriptionSection));
            }

            if (deprecated)
            {
                var shortDeprecationText = DeprecatedWarning + "\r" + deprecationSummary;
                var longDeprecationText  = shortDeprecationText + (String.IsNullOrWhiteSpace(deprecationDetails) ? "" : "\r") + deprecationDetails;
                this.Summary      += "\r" + longDeprecationText;
                this.ShortSummary  = shortDeprecationText;
                this.Documentation = deprecationSummary;
            }
        }
Пример #23
0
            public void WriteTo(TextWriter writer, HtmlEncoder encoder)
            {
                var pipeline = new MarkdownPipelineBuilder().DisableHtml().Build();

                Markdig.Markdown.ToHtml(_markdown, writer, pipeline);
            }
Пример #24
0
        public static void VerifyMarkup(
            string markdown,
            string html,
            string[] errors       = null,
            string[] dependencies = null,
            bool lineNumber       = false,
            string filePath       = "test.md",
            Dictionary <string, string> tokens = null,
            Dictionary <string, string> files  = null,
            Action <MarkdownObject> verifyAST  = null)
        {
            errors = errors ?? Array.Empty <string>();
            tokens = tokens ?? new Dictionary <string, string>();
            files  = files ?? new Dictionary <string, string>();

            var actualErrors       = new List <string>();
            var actualDependencies = new HashSet <string>();

            var markdownContext = new MarkdownContext(
                getToken: key => tokens.TryGetValue(key, out var value) ? value : null,
                logInfo: (a, b, c, d) => { },
                logSuggestion: Log("suggestion"),
                logWarning: Log("warning"),
                logError: Log("error"),
                readFile: ReadFile);

            var pipelineBuilder = new MarkdownPipelineBuilder()
                                  .UseDocfxExtensions(markdownContext)
                                  .UseYamlFrontMatter();

            if (lineNumber)
            {
                pipelineBuilder.UseLineNumber();
            }

            var pipeline = pipelineBuilder.Build();

            using (InclusionContext.PushFile(filePath))
            {
                var actualHtml = Markdown.ToHtml(markdown, pipeline);

                if (html != null)
                {
                    Assert.Equal(
                        html.Replace("\r", "").Replace("\n", ""),
                        actualHtml.Replace("\r", "").Replace("\n", ""));
                }

                Assert.Equal(errors.OrderBy(_ => _), actualErrors.OrderBy(_ => _));

                if (dependencies != null)
                {
                    Assert.Equal(dependencies.OrderBy(_ => _), actualDependencies.OrderBy(_ => _));
                }
            }

            MarkdownContext.LogActionDelegate Log(string level)
            {
                return((code, message, origin, line) => actualErrors.Add(code));
            }

            (string content, object file) ReadFile(string path, object relativeTo, MarkdownObject origin)
            {
                var key = Path.Combine(Path.GetDirectoryName(relativeTo.ToString()), path).Replace('\\', '/');

                if (path.StartsWith("~/"))
                {
                    path = path.Substring(2);
                    key  = path;
                }

                actualDependencies.Add(path);
                return(files.TryGetValue(key, out var value) ? (value, key) : default);
Пример #25
0
 /// <summary>
 /// 使用Markdig扩展。
 /// </summary>
 /// <typeparam name="TExtension">扩展类型。</typeparam>
 /// <param name="builder">当前管道构建实例。</param>
 /// <returns>返回管道构建实例。</returns>
 public static MarkdownPipelineBuilder Use <TExtension>(this MarkdownPipelineBuilder builder)
     where TExtension : IMarkdownExtension, new()
 {
     return(builder.Use(new TExtension()));
 }
Пример #26
0
 public void Setup(MarkdownPipelineBuilder pipeline)
 {
     pipeline.BlockParsers.Find <ListBlockParser>()?.ItemParsers.AddIfNotAlready <CheckboxParser>();
 }
Пример #27
0
 public void Setup(MarkdownPipelineBuilder pipeline)
 {
     pipeline.InlineParsers.AddIfNotAlready <BlogMetadataParser>();
 }
Пример #28
0
        public static (DescriptionYaml Meta, string Style, Dictionary <string, string> Descriptions) ParseDescription(string input)
        {
            var pipeline = new MarkdownPipelineBuilder()
                           .UseYamlFrontMatter()
                           .Build();

            var document  = Markdown.Parse(input, pipeline);
            var yamlBlock = document.Descendants <YamlFrontMatterBlock>().FirstOrDefault();

            DescriptionYaml meta = null;

            if (yamlBlock != null)
            {
                var yaml = input.Substring(yamlBlock.Span.Start, yamlBlock.Span.Length).Trim('-');
                meta = Deserializer.FromValueDeserializer(new DeserializerBuilder()
                                                          .WithNamingConvention(CamelCaseNamingConvention.Instance).BuildValueDeserializer())
                       .Deserialize <DescriptionYaml>(yaml);
            }

            var isAfterEnHeading = false;
            var isStyleBlock     = false;
            var isCodeBlock      = false;

            var zhPart    = "";
            var enPart    = "";
            var stylePart = "";
            var codePart  = "";

            for (var i = yamlBlock?.Line ?? 0; i < document.Count; i++)
            {
                var block = document[i];
                if (block is YamlFrontMatterBlock)
                {
                    continue;
                }

                if (block is HeadingBlock heading && heading.Level == 2 && heading.Inline.FirstChild.ToString() == "en-US")
                {
                    isAfterEnHeading = true;
                }

                if (block is CodeBlock codeBlock)
                {
                    isCodeBlock = true;
                }

                if (block is HtmlBlock htmlBlock && htmlBlock.Type == HtmlBlockType.ScriptPreOrStyle)
                {
                    isStyleBlock = true;
                }

                if (block is HeadingBlock h && h.Level == 2)
                {
                    continue;
                }

                using var writer = new StringWriter();
                var renderer = new HtmlRenderer(writer);

                var blockHtml = renderer.Render(block);

                if (!isAfterEnHeading)
                {
                    zhPart += blockHtml;
                }
                else if (isStyleBlock)
                {
                    stylePart += blockHtml;
                }
                //else if (isCodeBlock)
                //{
                //    codePart += blockHtml;
                //}
                else
                {
                    enPart += blockHtml;
                }
            }

            stylePart = stylePart.Replace("<style>", "").Replace("</style>", "");
            return(meta, stylePart, new Dictionary <string, string>()
            {
Пример #29
0
 public void Setup(MarkdownPipelineBuilder pipeline)
 {
     // Make sure we don't have a delegate twice
     pipeline.DocumentProcessed -= PipelineOnDocumentProcessed;
     pipeline.DocumentProcessed += PipelineOnDocumentProcessed;
 }
 /// <summary>
 /// Adds a new <see cref="SyntaxHighlighterMarkdownExtension"/> to the specified Markdig <paramref name="pipeline"/>.
 /// </summary>
 /// <param name="pipeline">The pipeline.</param>
 /// <param name="options">The options for configuration the syntax highlighter extension.</param>
 /// <returns>The pipeline.</returns>
 public static MarkdownPipelineBuilder UseSyntaxHighlighter(this MarkdownPipelineBuilder pipeline, out SyntaxHighlighterOptions options)
 {
     options = new SyntaxHighlighterOptions();
     pipeline.Extensions.Add(new SyntaxHighlighterMarkdownExtension(options));
     return(pipeline);
 }
Пример #31
0
 public static MarkdownPipelineBuilder UseQuoteSectionNote(this MarkdownPipelineBuilder pipeline, MarkdownServiceParameters parameters)
 {
     pipeline.Extensions.Insert(0, new QuoteSectionNoteExtension(parameters));
     return(pipeline);
 }
 /// <summary>
 /// Setups this extension for the specified pipeline.
 /// </summary>
 /// <param name="pipeline">The pipeline.</param>
 public void Setup(MarkdownPipelineBuilder pipeline)
 {
 }
Пример #33
0
 public static MarkdownPipelineBuilder UseCodeSnippet(this MarkdownPipelineBuilder pipeline, MarkdigCompositor compositor, MarkdownContext context)
 {
     pipeline.Extensions.Insert(0, new CodeSnippetExtension(compositor, context));
     return(pipeline);
 }
 public void Setup(MarkdownPipelineBuilder pipeline) {}
Пример #35
0
 public static MarkdownPipelineBuilder UseXref(this MarkdownPipelineBuilder pipeline)
 {
     pipeline.Extensions.Insert(0, new XrefInlineExtension());
     return(pipeline);
 }