/// <summary>
        /// Converts the <see cref="Message.Contents"/> of <paramref name="message"/> to HTML.
        /// </summary>
        public static string GetHtmlContents(this Message message)
        {
            var pipelineBuilder = new MarkdownPipelineBuilder();

            pipelineBuilder.DisableHtml();
            return(Markdown.ToHtml(message.Contents, pipelineBuilder.Build()));
        }
Exemple #2
0
        public static string MarkupArticle(string secdata, bool forum, bool frontPage = false)
        {
            var pipelineBuilder = new MarkdownPipelineBuilder()
                                  .UseAdvancedExtensions();

            if (forum)
            {
                pipelineBuilder.DisableHtml();
            }
            var pipeline = pipelineBuilder.Build();

            //Parse and Render Markup while applying special optimizations
            //Shamelessly ripped off from https://github.com/lunet-io/markdig/issues/293#issuecomment-456376415
            var document = Markdown.Parse(secdata, pipeline);

            foreach (var descendant in document.Descendants())
            {
                string url     = null;
                bool   isImage = false;
                if (descendant is AutolinkInline autoLink)
                {
                    url = autoLink.Url;
                }
                else if (descendant is LinkInline linkInline)
                {
                    url     = linkInline.Url;
                    isImage = linkInline.IsImage;
                    if (isImage && !Shared.Helpers.IsUrlAbsolute(url))
                    {
                        var imageUrl       = url.TrimStart('/');
                        var imageHashEntry = ContentHash.GetContentHashEntryForFile(SystemInfoHelpers.ContentRootPath, "wwwroot", imageUrl, Html.GetRelativeHashPath, true).Result;
                        if (imageHashEntry != null)
                        {
                            linkInline.Url = url = Html.GetRelativeHashPath(imageHashEntry.Hash, imageHashEntry.WebPath);
                        }
                    }
                }
                if (!isImage && Shared.Helpers.IsUrlAbsolute(url))
                {
                    descendant.GetAttributes().AddPropertyIfNotExist("target", "_blank");
                }
            }
            using (var writer = new StringWriter())
            {
                var renderer = new HtmlRenderer(writer);
                pipeline.Setup(renderer);
                renderer.Render(document);

                //Return finalized HTML
                if (!frontPage || !Settings.Current.SummaryModeFront)
                {
                    return(writer.ToString());
                }
                return(writer.ToString().DataTruncate(-3));
            }
        }
Exemple #3
0
        private static MarkdownPipeline CreateUntrustedPipeline()
        {
            var pb = new MarkdownPipelineBuilder();

            pb.DisableHtml();
            pb.DisableHeadings();
            pb.InlineParsers.TryRemove <LinkInlineParser>();

            return(pb.Build());
        }
Exemple #4
0
        public static string MarkupArticle(string secdata, bool forum)
        {
            var pipeline = new MarkdownPipelineBuilder()
                           .UseAdvancedExtensions();

            if (forum)
            {
                pipeline.DisableHtml();
            }
            return(Markdown.ToHtml(secdata, pipeline.Build()));
        }
Exemple #5
0
        public void ParseMarkdownWithDisabledHtml(string data, string expected, bool disableHtml)
        {
            var builder = new MarkdownPipelineBuilder();

            if (disableHtml)
            {
                builder.DisableHtml();
            }
            var parsedResults = Markdown.ToHtml(data, builder.Build());

            Assert.AreEqual(expected, parsedResults);
        }
        static Renderer()
        {
            _NormalizeOptions = new Nr.NormalizeOptions
            {
                ListItemCharacter = '-',
            };
            var builder = new MarkdownPipelineBuilder();

            builder.DisableHtml();
            builder.BlockParsers.RemoveAll(bp => !(bp is Markdig.Parsers.ParagraphBlockParser));
            builder.UseAutoLinks();
            _Pipeline = builder.Build();
        }
Exemple #7
0
        /// <summary>
        /// Builds the Markdig processing pipeline and returns a builder.
        /// Use this method to override any custom pipeline addins you want to
        /// add or append.
        ///
        /// Note you can also add addins using options.MarkdigExtensions which
        /// use MarkDigs extension syntax using commas instead of +.
        /// </summary>
        /// <param name="options"></param>
        /// <param name="builder"></param>
        /// <returns></returns>
        protected virtual MarkdownPipelineBuilder BuildPipeline(MarkdownOptionsConfiguration options, MarkdownPipelineBuilder builder)
        {
            if (options.AutoLinks)
            {
                builder = builder.UseAutoLinks();
            }
            if (options.AutoHeaderIdentifiers)
            {
                builder = builder.UseAutoIdentifiers(Markdig.Extensions.AutoIdentifiers.AutoIdentifierOptions.GitHub);
            }
            if (options.Abbreviations)
            {
                builder = builder.UseAbbreviations();
            }

            if (options.UseTables)
            {
                builder = builder
                          .UsePipeTables()
                          .UseGridTables();
            }

            if (options.StripYamlFrontMatter)
            {
                builder = builder.UseYamlFrontMatter();
            }
            if (options.EmojiAndSmiley)
            {
                builder = builder.UseEmojiAndSmiley(true);
            }
            if (options.MediaLinks)
            {
                builder = builder.UseMediaLinks();
            }
            if (options.ListExtras)
            {
                builder = builder.UseListExtras();
            }
            if (options.Figures)
            {
                builder = builder.UseFigures();
            }
            if (options.GithubTaskLists)
            {
                builder = builder.UseTaskLists();
            }
            if (options.SmartyPants)
            {
                builder = builder.UseSmartyPants();
            }
            if (options.Diagrams)
            {
                builder = builder.UseDiagrams();
            }
            if (options.CustomContainers)
            {
                builder = builder.UseCustomContainers();
            }
            if (options.Attributes)
            {
                builder = builder.UseGenericAttributes();
            }
            if (options.FootersAndFootnotes)
            {
                builder = builder
                          .UseFooters()
                          .UseFootnotes();
            }
            if (options.NoHtml)
            {
                builder = builder.DisableHtml();
            }

            builder = builder.UseEmphasisExtras();

            if (UsePragmaLines)
            {
                builder = builder.UsePragmaLines();
            }

            try
            {
                if (!string.IsNullOrWhiteSpace(options.MarkdigExtensions))
                {
                    builder = builder.Configure(options.MarkdigExtensions.Replace(",", "+"));
                }
            }
            catch (ArgumentException ex)
            {
                // One or more of the extension options is invalid.
                mmApp.Log("Failed to load Markdig extensions: " + options.MarkdigExtensions + "\r\n" + ex.Message, ex);

                // reset to default
                options.MarkdigExtensions = string.Empty;
                builder = builder.Configure(options.MarkdigExtensions.Replace(",", "+"));
            }

            return(builder);
        }
        /// <summary>
        /// Parses the actual markdown down to html
        /// </summary>
        /// <param name="markdown"></param>
        /// <returns></returns>
        public override string Parse(string markdown)
        {
            var options = mmApp.Configuration.MarkdownOptions;

            var builder = new MarkdownPipelineBuilder();

            var errors = Array.Empty <string>();
            var tokens = new Dictionary <string, string>();
            var files  = new Dictionary <string, string>();

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

            var context = 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);


            // Fake root path to what MM sees as the root path (.markdown, project file, project open etc.)
            string filePath = mmApp.Model.ActiveDocument?.Filename;

            if (string.IsNullOrEmpty(filePath) || filePath.Equals("untitled", StringComparison.OrdinalIgnoreCase))
            {
                filePath = mmApp.Model.ActiveDocument?.PreviewWebRootPath;
                if (string.IsNullOrEmpty(filePath))
                {
                    filePath = "preview.md";
                }
                else
                {
                    filePath += "\\preview";
                }
            }

            files.Add(filePath, markdown);


            builder = builder.UseEmphasisExtras(EmphasisExtraOptions.Strikethrough)
                      .UseAutoIdentifiers(AutoIdentifierOptions.GitHub)
                      .UseMediaLinks()
                      .UsePipeTables()
                      .UseAutoLinks()
                      .UseHeadingIdRewriter()
                      .UseIncludeFile(context)
                      .UseCodeSnippet(context)
                      .UseDFMCodeInfoPrefix()
                      .UseQuoteSectionNote(context)
                      .UseXref()
                      .UseEmojiAndSmiley(false)
                      .UseTabGroup(context)
                      .UseMonikerRange(context)
                      .UseInteractiveCode()
                      .UseRow(context)
                      .UseNestedColumn(context)
                      .UseTripleColon(context)
                      .UseNoloc();



            builder = RemoveUnusedExtensions(builder);
            builder = builder
                      .UseYamlFrontMatter()
                      .UseLineNumber();

            if (options.NoHtml)
            {
                builder = builder.DisableHtml();
            }

            if (UsePragmaLines)
            {
                builder = builder.UsePragmaLines();
            }

            var pipeline = builder.Build();

            string html;

            using (InclusionContext.PushFile(filePath))
            {
                html = Markdown.ToHtml(markdown, pipeline);
            }

            html = ParseFontAwesomeIcons(html);


            if (mmApp.Configuration.MarkdownOptions.RenderLinksAsExternal)
            {
                html = ParseExternalLinks(html);
            }

            if (!mmApp.Configuration.MarkdownOptions.AllowRenderScriptTags)
            {
                html = HtmlUtils.SanitizeHtml(html);
            }


            return(html);


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

            // Handler to fix up file paths for nested/included documents
            (string content, object file) ReadFile(string path, MarkdownObject origin)
            {
                string key;

                var rootPath = mmApp.Model.ActiveDocument?.PreviewWebRootPath;

                if (rootPath == null)
                {
                    rootPath = Path.GetDirectoryName(files.FirstOrDefault().Key);
                }


                string parentDocPath = null; //relativeTo as string;   NOT PROVIDEd BY DOCFX ANYMORE???

                //if (!string.IsNullOrEmpty(parentDocPath))
                //    parentDocPath = Path.GetDirectoryName(parentDocPath);


                //fully qualified path
                if (path.Contains(":/") || path.Contains(":\\"))
                {
                    key = path;
                }
                else if (!string.IsNullOrEmpty(rootPath) && path.StartsWith("~/"))
                {
                    path = path.Substring(2);
                    key  = Path.Combine(rootPath, path).Replace('\\', '/');
                }
                // Site relative  path
                else if (!string.IsNullOrEmpty(rootPath) && path.StartsWith("/"))
                {
                    path = path.Substring(1);
                    key  = Path.Combine(rootPath, path).Replace('\\', '/');
                }
                // Site relative path
                else if (!string.IsNullOrEmpty(parentDocPath))
                {
                    key = Path.GetFullPath(Path.Combine(parentDocPath, path));
                }
                else
                {
                    key = path;
                }

                actualDependencies.Add(key);

                files.TryGetValue(key, out var value);
                if (value == null)
                {
                    try
                    {
                        value = File.ReadAllText(key)?.Trim();
                    }
                    catch
                    {
                    }
                }

                if (value == null)
                {
                    return(null, null);
                }

                return(value, key as object);
            }
        }
Exemple #9
0
        /// <summary>
        /// Parses the actual markdown down to html
        /// </summary>
        /// <param name="markdown"></param>
        /// <returns></returns>
        public override string Parse(string markdown)
        {
            var options = mmApp.Configuration.MarkdownOptions;

            var builder = new MarkdownPipelineBuilder();

            var errors = Array.Empty <string>();
            var tokens = new Dictionary <string, string>();
            var files  = new Dictionary <string, string>();

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

            var context = 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);


            // Fake root path to what MM sees as the root path (.markdown, project file, project open etc.)
            string filePath = mmApp.Model.ActiveDocument?.Filename;

            if (string.IsNullOrEmpty(filePath) || filePath.Equals("untitled", StringComparison.OrdinalIgnoreCase))
            {
                filePath = mmApp.Model.ActiveDocument?.PreviewWebRootPath;
                if (string.IsNullOrEmpty(filePath))
                {
                    filePath = "preview.md";
                }
                else
                {
                    filePath += "\\preview";
                }
            }
            files.Add(filePath, markdown);


            builder = builder.UseEmphasisExtras(EmphasisExtraOptions.Strikethrough)
                      .UseAutoIdentifiers(AutoIdentifierOptions.GitHub)
                      .UseMediaLinks()
                      .UsePipeTables()
                      .UseAutoLinks()
                      .UseHeadingIdRewriter()
                      .UseIncludeFile(context)
                      .UseCodeSnippet(context)
                      .UseDFMCodeInfoPrefix()
                      .UseQuoteSectionNote(context)
                      .UseXref()
                      .UseEmojiAndSmiley(false)
                      .UseTabGroup(context)
                      .UseMonikerRange(context)
                      .UseInteractiveCode()
                      .UseRow(context)
                      .UseNestedColumn(context)
                      .UseTripleColon(context)
                      .UseNoloc();



            builder = RemoveUnusedExtensions(builder);
            builder = builder
                      .UseYamlFrontMatter()
                      .UseLineNumber();

            if (options.NoHtml)
            {
                builder = builder.DisableHtml();
            }

            if (UsePragmaLines)
            {
                builder = builder.UsePragmaLines();
            }

            var pipeline = builder.Build();

            string html;

            try
            {
                using (InclusionContext.PushFile(filePath))
                {
                    html = Markdown.ToHtml(markdown, pipeline);
                }

                html = ParseFontAwesomeIcons(html);
            }
            catch (Exception ex)
            {
                if (markdown.Length > 10000)
                {
                    markdown = markdown.Substring(0, 10000);
                }

                mmApp.Log("Unable to render Markdown Document (docFx)\n" + markdown, ex, logLevel: LogLevels.Warning);
                html = $@"
<h1><i class='fa fa-warning text-error'></i> Unable to render Markdown Document</h1>

<p>
   An error occurred trying to parse the Markdown document to HTML:
</p>

<b style='font-size: 1.2em'>{ex.Message}</b>

<p>
    <a id='hrefShow' href='#0' style='font-size: 0.8em; font-weight: normal'>more info...</a>
</p>

<div id='detail' style='display:none'>


<p style='margin-top: 2em'>
    <b>Markdown Parser</b>: {options.MarkdownParserName}
</p>


<pre style='padding: 8px; background: #eee; color: #333' >{System.Net.WebUtility.HtmlEncode(StringUtils.NormalizeIndentation(ex.StackTrace))}</pre>
</div>

<script>
$('#hrefShow').click(function () {{ $('#detail').show(); }});
</script>
";
                return(html);
            }

            if (mmApp.Configuration.MarkdownOptions.RenderLinksAsExternal)
            {
                html = ParseExternalLinks(html);
            }

            if (!mmApp.Configuration.MarkdownOptions.AllowRenderScriptTags)
            {
                html = HtmlUtils.SanitizeHtml(html);
            }


            return(html);


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

            // Handler to fix up file paths for nested/included documents
            (string content, object file) ReadFile(string path, object relativeTo, MarkdownObject origin)
            {
                string key;
                var    relativeDocumentPath = relativeTo as string;

                var rootPath = mmApp.Model.ActiveDocument?.PreviewWebRootPath;

                if (rootPath == null)
                {
                    rootPath = Path.GetDirectoryName(files.FirstOrDefault().Key);
                }
                var parentDocPath = relativeTo as string;

                if (!string.IsNullOrEmpty(parentDocPath))
                {
                    parentDocPath = Path.GetDirectoryName(parentDocPath);
                }


                //fully qualified path
                if (path.Contains(":/") || path.Contains(":\\"))
                {
                    key = path;
                }
                else if (!string.IsNullOrEmpty(rootPath) && path.StartsWith("~/"))
                {
                    path = path.Substring(2);
                    key  = Path.Combine(rootPath, path).Replace('\\', '/');
                }
                // Site relative  path
                else if (!string.IsNullOrEmpty(rootPath) && path.StartsWith("/"))
                {
                    path = path.Substring(1);
                    key  = Path.Combine(rootPath, path).Replace('\\', '/');
                }
                // Site relative path
                else if (!string.IsNullOrEmpty(parentDocPath))
                {
                    key = Path.GetFullPath(Path.Combine(parentDocPath, path));
                }
                else
                {
                    key = path;
                }

                actualDependencies.Add(key);

                files.TryGetValue(key, out var value);
                if (value == null)
                {
                    try
                    {
                        value = File.ReadAllText(key)?.Trim();
                    }catch { }
                }

                if (value == null)
                {
                    return(null, null);
                }

                return(value, key as object);
            }
        }
Exemple #10
0
        private async Task <MarkdownPipeline> GetMarkdownPipelineImpl(HtmlBuilder htmlBuilder)
        {
            var pipelineBuilder = new MarkdownPipelineBuilder();


            htmlBuilder.UseVSCodeMarkdownStylesheet();
            htmlBuilder.AddKeyboardListener();
            htmlBuilder.AddCharset();

            if (!await _settings.IsHtmlEnabled())
            {
                pipelineBuilder.DisableHtml();
            }
            if (await _settings.IsAbbreviationEnabled())
            {
                pipelineBuilder.UseAbbreviations();
            }
            // TODO AutoIdentifierOptions
            if (await _settings.IsAutoIdentifierEnabled())
            {
                pipelineBuilder.UseAutoIdentifiers();
            }
            if (await _settings.IsBootstrapEnabled())
            {
                pipelineBuilder.UseBootstrap();
            }
            if (await _settings.IsCitationEnabled())
            {
                pipelineBuilder.UseCitations();
            }
            if (await _settings.IsDefinitionListEnabled())
            {
                pipelineBuilder.UseDefinitionLists();
            }
            // TODO EmojiSmileyOptions
            if (await _settings.IsEmojiSmileyEnabled())
            {
                pipelineBuilder.UseEmojiAndSmiley();
            }
            if (await _settings.IsFigureEnabled())
            {
                pipelineBuilder.UseFigures();
            }
            if (await _settings.IsFooterEnabled())
            {
                pipelineBuilder.UseFooters();
            }
            if (await _settings.IsFootnoteEnabled())
            {
                pipelineBuilder.UseFootnotes();
            }
            // TODO MediaLinkOptions
            if (await _settings.IsMedialinkEnabled())
            {
                pipelineBuilder.UseMediaLinks();
            }
            if (await _settings.IsSoftlineAsHardlineBreakEnabled())
            {
                pipelineBuilder.UseSoftlineBreakAsHardlineBreak();
            }
            // TODO SmartyPantsOptions
            if (await _settings.IsSmartyPantEnabled())
            {
                pipelineBuilder.UseSmartyPants();
            }
            if (await _settings.IsGenericAttributeEnabled())
            {
                pipelineBuilder.UseGenericAttributes();
            }

            if (await _settings.IsDiagramEnabled())
            {
                pipelineBuilder.UseDiagrams();

                if (await _settings.IsMermaidEnabled())
                {
                    htmlBuilder.UseMermaid();
                }
                if (await _settings.IsNomnomlEnabled())
                {
                    htmlBuilder.UseNomnoml();
                }
            }

            if (await _settings.IsEmphasisEnabled())
            {
                EmphasisExtraOptions options = 0;

                if (await _settings.IsStrikethroughEnabled())
                {
                    options |= EmphasisExtraOptions.Strikethrough;
                }
                if (await _settings.IsInsertedEnabled())
                {
                    options |= EmphasisExtraOptions.Inserted;
                }
                if (await _settings.IsMarkedEnabled())
                {
                    options |= EmphasisExtraOptions.Marked;
                }
                if (await _settings.IsSuperSubScriptEnabled())
                {
                    options = options | EmphasisExtraOptions.Subscript | EmphasisExtraOptions.Superscript;
                }

                pipelineBuilder.UseEmphasisExtras(options);
            }

            if (await _settings.IsListEnabled())
            {
                if (await _settings.IsTaskListEnabled())
                {
                    pipelineBuilder.UseTaskLists();
                }
                if (await _settings.IsListExtraEnabled())
                {
                    pipelineBuilder.UseListExtras();
                }
            }

            if (await _settings.IsMathEnabled())
            {
                pipelineBuilder.UseMyMathExtension();
                htmlBuilder.UseMathjax();
            }

            if (await _settings.IsSyntaxHighlightingEnabled())
            {
                htmlBuilder.UsePrismSyntaxHighlighting();
            }

            if (await _settings.IsTableEnabled())
            {
                if (await _settings.IsGridTableEnabled())
                {
                    pipelineBuilder.UseGridTables();
                }
                // TODO PipeTableOptions
                if (await _settings.IsPipeTableEnabled())
                {
                    pipelineBuilder.UsePipeTables();
                }
            }

            pipelineBuilder.UseMyWikiLinkExtension();
            pipelineBuilder.UseTagExtension();
            pipelineBuilder.UseYamlFrontMatter();

            htmlBuilder.Flush();

            return(pipelineBuilder.Build());
        }