Пример #1
0
 public static Syntax.Block ParseDocument(string commonMark, CommonMarkSettings settings = null)
 {
     using (var reader = new System.IO.StringReader(Helpers.Normalize(commonMark)))
     {
         return CommonMarkConverter.Parse(reader, settings);
     }
 }
Пример #2
0
 private static Formatters.HtmlFormatter CreatePrintPlaceholdersWithColonDollarExcludesBHtmlFormatter(System.IO.TextWriter target, CommonMarkSettings stngs)
 {
     return new Formatters.HtmlFormatter(target, stngs)
     {
         PlaceholderResolver = placeholder => placeholder.Contains("b") ? null : ":" + placeholder + "$"
     };
 }
Пример #3
0
 static Markdown()
 {
     settings = CommonMarkSettings.Default.Clone();
     settings.OutputFormat   = OutputFormat.CustomDelegate;
     settings.OutputDelegate =
         (doc, output, settings) => new CustomHtmlFormatter(output, settings).WriteDocument(doc);
 }
Пример #4
0
        public static void markdown2html(ApplicationContext context, ActiveEventArgs e)
        {
            // Making sure we clean up and remove all arguments passed in after execution
            using (new ArgsRemover(e.Args, false)) {
                // Assumes there's only one document, or creates one result of it.
                var md = XUtil.Single <string> (context, e.Args);

                // Making sure we correctly resolve URLs, if user specified a [root-url] argument.
                var root = e.Args.GetExChildValue("root-url", context, "");
                CommonMarkSettings settings = CommonMarkSettings.Default;
                if (root != "")
                {
                    // Unrolling path.
                    root = context.RaiseEvent("p5.io.unroll-path", new Node("", root)).Get <string> (context);

                    // To make sure we don't change global settings.
                    settings             = settings.Clone();
                    settings.UriResolver = delegate(string arg) {
                        if (arg.StartsWithEx("http://") || arg.StartsWithEx("https://"))
                        {
                            return(arg);
                        }
                        return(root + arg.TrimStart('/'));
                    };
                }

                // Doing actual conversion.
                e.Args.Value = CommonMarkConverter.Convert(md, settings);
            }
        }
Пример #5
0
        public MarkdownLoader(IHostingEnvironment environment, ILoggerFactory loggerFactory)
        {
            fileProvider       = environment.ContentRootFileProvider;
            commonMarkSettings = CommonMarkSettings.Default.Clone();
            bundles            = new Dictionary <string, MarkdownBundle>();

            // Lets us resolve numbers to issue links.
            commonMarkSettings.AdditionalFeatures = CommonMarkAdditionalFeatures.PlaceholderBracket;
            commonMarkSettings.OutputDelegate     = FormatDocument;
            // May become obsolete, if we can resolve [NodaTime.LocalDateTime] to the right type link etc.
            commonMarkSettings.UriResolver = ResolveUrl;

            var logger    = loggerFactory.CreateLogger <MarkdownLoader>();
            var stopwatch = Stopwatch.StartNew();

            // TODO: Make the root location configurable
            LoadBundleMetadata("Markdown");
            PopulateParentBundles();
            LoadBundleContent();

            var totalPages = bundles.Values.SelectMany(b => b.Categories).Sum(c => c.Pages.Count);

            logger.LogInformation("Loaded {bundleCount} bundles totalling {pageCount} pages in {durationMs}ms",
                                  bundles.Count, totalPages, stopwatch.ElapsedMilliseconds);
        }
Пример #6
0
        private MarkdownPage LoadPage(IFileProvider fileProvider, CommonMarkSettings commonMarkSettings, string id)
        {
            var filename = $"{ContentDirectory}/{id}.md";

            try
            {
                var file = fileProvider.GetFileInfo(filename);
                if (!file.Exists)
                {
                    if (ParentBundle == null)
                    {
                        throw new Exception($"Unable to find {file.Name} for bundle {Name} and no parent bundle exists");
                    }
                    var page = ParentBundle.TryGetPage(id);
                    if (page == null)
                    {
                        throw new Exception($"Unable to find {file.Name} for bundle {Name} and parent bundle doesn't have the page");
                    }
                    return(page.WithBundle(this));
                }
                using (var reader = file.CreateReader())
                {
                    return(MarkdownPage.Load(id, this, reader, commonMarkSettings));
                }
            }
            catch (Exception e)
            {
                throw new Exception($"Unable to parse markdown content from {filename}", e);
            }
        }
Пример #7
0
        /// <summary>
        /// Initializes the array of delegates for inline parsing.
        /// </summary>
        /// <returns></returns>
        internal static Func<Subject, Inline>[] InitializeParsers(CommonMarkSettings settings)
        {
            var strikethroughTilde = 0 != (settings.AdditionalFeatures & CommonMarkAdditionalFeatures.StrikethroughTilde);
            var placeholderBracket = 0 != (settings.AdditionalFeatures & CommonMarkAdditionalFeatures.PlaceholderBracket);

            var p = new Func<Subject, Inline>[strikethroughTilde ? 127 : 97];
            p['\n'] = handle_newline;
            p['`'] = handle_backticks;
            p['\\'] = handle_backslash;
            p['&'] = HandleEntity;
            p['<'] = handle_pointy_brace;
            p['_'] = HandleEmphasis;
            p['*'] = HandleEmphasis;
            p['['] = HandleLeftSquareBracket;

            if (placeholderBracket)
                p[']'] = subj => HandleRightSquareBracket(subj, true);
            else
                p[']'] = subj => HandleRightSquareBracket(subj, false);
            
            p['!'] = HandleExclamation;

            if (strikethroughTilde)
                p['~'] = HandleTilde;

            return p;
        }
Пример #8
0
        /// <summary>
        /// Initializes the array of delegates for inline parsing.
        /// </summary>
        /// <returns></returns>
        internal static Func <Subject, Inline>[] InitializeParsers(CommonMarkSettings settings)
        {
            var strikethroughTilde = 0 != (settings.AdditionalFeatures & CommonMarkAdditionalFeatures.StrikethroughTilde);
            var placeholderBracket = 0 != (settings.AdditionalFeatures & CommonMarkAdditionalFeatures.PlaceholderBracket);

            var p = new Func <Subject, Inline> [strikethroughTilde ? 127: 97];

            p['\n'] = handle_newline;
            p['`']  = handle_backticks;
            p['\\'] = handle_backslash;
            p['&']  = HandleEntity;
            p['<']  = handle_pointy_brace;
            p['_']  = HandleEmphasis;
            p['*']  = HandleEmphasis;
            p['[']  = HandleLeftSquareBracket;

            if (placeholderBracket)
            {
                p[']'] = subj => HandleRightSquareBracket(subj, true);
            }
            else
            {
                p[']'] = subj => HandleRightSquareBracket(subj, false);
            }

            p['!'] = HandleExclamation;

            if (strikethroughTilde)
            {
                p['~'] = HandleTilde;
            }

            return(p);
        }
Пример #9
0
        /// <summary>
        /// Initializes the array of delegates for inline parsing.
        /// </summary>
        /// <returns></returns>
        internal static Func<Subject, Inline>[] InitializeParsers(CommonMarkSettings settings)
        {
            var singleCharTags = settings.InlineParserParameters.SingleCharTags;
            var doubleCharTags = settings.InlineParserParameters.DoubleCharTags;
            var length = singleCharTags.Length >= doubleCharTags.Length
                ? singleCharTags.Length
                : doubleCharTags.Length;

            var p = new Func<Subject, Inline>[length];
            p['\n'] = handle_newline;
            p['`'] = handle_backticks;
            p['\\'] = handle_backslash;
            p['&'] = HandleEntity;
            p['<'] = handle_pointy_brace;
            p['['] = s => HandleLeftSquareBracket(s, settings);
            p[']'] = s => HandleRightSquareBracket(s, settings);
            p['!'] = s => HandleExclamation(s, settings);

            for (int i = 0; i < length; i++)
            {
                var singleCharTag = i < singleCharTags.Length ? singleCharTags[i] : (InlineTag)0;
                var doubleCharTag = i < doubleCharTags.Length ? doubleCharTags[i] : (InlineTag)0;
                if (singleCharTag != 0 || doubleCharTag != 0)
                    p[i] = s => HandleOpenerCloser(s, singleCharTag, doubleCharTag, settings.InlineParserParameters);
            }

            return p;
        }
Пример #10
0
 public static Syntax.Block ParseDocument(string commonMark, CommonMarkSettings settings = null)
 {
     using (var reader = new System.IO.StringReader(Helpers.Normalize(commonMark)))
     {
         return(CommonMarkConverter.Parse(reader, settings));
     }
 }
Пример #11
0
 static TelemetryNotice()
 {
     CommonMarkSettings = CommonMarkSettings.Default.Clone();
     CommonMarkSettings.AdditionalFeatures |=
         CommonMarkAdditionalFeatures.PlaceholderBracket;
     CommonMarkSettings.UriResolver = UrlResolver;
 }
Пример #12
0
        public static void ExecuteTest(string commonMark, string html, CommonMarkSettings settings = null, Func<System.IO.TextWriter, CommonMarkSettings, Formatters.HtmlFormatter> htmlFormatterFactory = null)
        {
            if (settings == null)
                settings = CommonMarkSettings.Default.Clone();

            Helpers.LogValue("CommonMark", Denormalize(commonMark));
            Helpers.LogValue("Expected", Denormalize(html));

            // Arrange
            commonMark = Helpers.Normalize(commonMark);
            html = Helpers.Normalize(html);
            
            string actual;
            Syntax.Block document;

            // Act
            using (var reader = new System.IO.StringReader(commonMark))
            using (var writer = new System.IO.StringWriter())
            {
                if (htmlFormatterFactory != null)
                {
                    settings = settings.Clone();
                    settings.OutputFormat = OutputFormat.CustomDelegate;
                    settings.OutputDelegate = (doc, target, stngs) => htmlFormatterFactory(target, stngs).WriteDocument(doc);
                }

                document = CommonMarkConverter.ProcessStage1(reader, settings);
                CommonMarkConverter.ProcessStage2(document, settings);
                CommonMarkConverter.ProcessStage3(document, writer, settings);
                actual = writer.ToString();
            }

            // Assert
            Helpers.LogValue("Actual", Denormalize(actual));
            actual = Helpers.Tidy(actual);
            Assert.AreEqual(Helpers.Tidy(html), actual);

            if (htmlFormatterFactory == null)
            {
                // Verify that the extendable HTML formatter returns the same result, unless
                // the test was run with a custom extendable HTML formatter factory. In the
                // latter case, only the output of the custom extendable HTML formatter is
                // verified.
                var settingsHtmlFormatter = settings.Clone();
                settingsHtmlFormatter.OutputDelegate = (doc, target, stngs) => new Formatters.HtmlFormatter(target, stngs).WriteDocument(doc);
                var actual2 = CommonMarkConverter.Convert(commonMark, settingsHtmlFormatter);
                Assert.AreEqual(actual, Helpers.Tidy(actual2), "HtmlFormatter returned a different result than HtmlFormatterSlim.");
            }

            // Additionally verify that the parser included source position information.
            // This is done here to catch cases during specification tests that might not be 
            // covered in SourcePositionTests.cs.
            var firstFail = document.AsEnumerable().FirstOrDefault(o => o.Inline != null && o.IsOpening && o.Inline.SourceLength <= 0);
            if (firstFail != null)
            {
                Assert.Fail("Incorrect source position: " + firstFail);
            }
        }
Пример #13
0
 internal void LoadContent(IFileProvider fileProvider, CommonMarkSettings commonMarkSettings)
 {
     foreach (var category in Categories)
     {
         category.Pages = category.PageIds.Select(id => LoadPage(fileProvider, commonMarkSettings, id)).ToList();
     }
     resourcesById = Resources.ToDictionary(id => id, id => LoadResource(fileProvider, id));
     pagesById     = Categories.SelectMany(c => c.Pages).ToDictionary(p => p.Id);
 }
Пример #14
0
        private void FormatDocument(Block block, TextWriter writer, CommonMarkSettings settings)
        {
            var formatter = new HtmlFormatter(writer, settings)
            {
                PlaceholderResolver = ResolvePlaceholder
            };

            formatter.WriteDocument(block);
        }
Пример #15
0
        /// <summary>
        /// Walk through the block, its children and siblings, parsing string content into inline content where appropriate.
        /// </summary>
        /// <param name="block">The document level block from which to start the processing.</param>
        /// <param name="data">Document data.</param>
        /// <param name="settings">The settings that influence how the inline parsing is performed.</param>
        public static void ProcessInlines(Block block, DocumentData data, CommonMarkSettings settings)
        {
            Stack <Inline> inlineStack       = null;
            var            stack             = new Stack <Block>();
            var            parsers           = settings.InlineParsers;
            var            specialCharacters = settings.InlineParserSpecialCharacters;
            var            subj = new Subject(data);

            StringContent sc;
            int           delta;

            while (block != null)
            {
                var tag = block.Tag;
                if (tag == BlockTag.Paragraph || tag == BlockTag.AtxHeading || tag == BlockTag.SetextHeading)
                {
                    sc = block.StringContent;
                    if (sc != null)
                    {
                        sc.FillSubject(subj);
                        delta = subj.Position;

                        block.InlineContent = InlineMethods.parse_inlines(subj, parsers, specialCharacters);
                        block.StringContent = null;

                        if (sc.PositionTracker != null)
                        {
                            sc.PositionTracker.AddBlockOffset(-delta);
                            AdjustInlineSourcePosition(block.InlineContent, sc.PositionTracker, ref inlineStack);
                        }
                    }
                }

                if (block.FirstChild != null)
                {
                    if (block.NextSibling != null)
                    {
                        stack.Push(block.NextSibling);
                    }

                    block = block.FirstChild;
                }
                else if (block.NextSibling != null)
                {
                    block = block.NextSibling;
                }
                else if (stack.Count > 0)
                {
                    block = stack.Pop();
                }
                else
                {
                    block = null;
                }
            }
        }
Пример #16
0
        /// <summary>Initializes a new instance of the <see cref="HtmlFormatter" /> class.</summary>
        /// <param name="target">The target text writer.</param>
        /// <param name="settings">The settings used when formatting the data.</param>
        /// <exception cref="ArgumentNullException">when <paramref name="target"/> is <see langword="null"/></exception>
        public HtmlFormatter(TextWriter target, CommonMarkSettings settings)
        {
            if (target == null)
                throw new ArgumentNullException(nameof(target));

            if (settings == null)
                settings = CommonMarkSettings.Default;

            _target = new HtmlTextWriter(target);
            _settings = settings;
        }
Пример #17
0
        internal static InlineTag[] InitializeDoubleCharTags(CommonMarkSettings settings)
        {
            var handleTilde = 0 != (settings.AdditionalFeatures & CommonMarkAdditionalFeatures.StrikethroughTilde);

            var t = InitializeEmphasisDoubleCharTags(handleTilde);

            if (handleTilde)
                t['~'] = InlineTag.Strikethrough;

            return t;
        }
Пример #18
0
        public static async Task <string> MarkdownToHTML(string markdownCode)
        {
            string htmlCode = null;
            await Task.Run(() => {
                CommonMarkSettings settings = CommonMarkSettings.Default;
                settings.OutputFormat       = OutputFormat.Html;
                settings.AdditionalFeatures = CommonMarkAdditionalFeatures.All;
                htmlCode = CommonMarkConverter.Convert(source: markdownCode, settings: settings);
            });

            return(htmlCode);
        }
Пример #19
0
        public async Task <string> ConvertToHtml(string mdFile, Func <string, string> resolveUri)
        {
            CommonMarkSettings settings = null;

            if (resolveUri != null)
            {
                settings             = CommonMarkSettings.Default.Clone();
                settings.UriResolver = resolveUri;
            }

            return(CommonMarkConverter.Convert(mdFile, settings));
        }
Пример #20
0
        static SemanticReleaseNotesFormatter()
        {
            DefaultCommonMarkSettings = CommonMarkSettings.Default.Clone();
            DefaultCommonMarkSettings.AdditionalFeatures = CommonMarkAdditionalFeatures.StrikethroughTilde;
            DefaultCommonMarkSettings.OutputFormat       = CommonMark.OutputFormat.Html;
            DefaultCommonMarkSettings.OutputDelegate     = (doc, output, settings) => new SemanticReleaseNotesHtmlFormatter(output, settings).WriteDocument(doc);

            Template.RegisterSafeType(typeof(Metadata), new[] { "Name", "Value" });
            Template.RegisterSafeType(typeof(ReleaseNotes), new[] { "Summary", "Sections", "Items", "Metadata" });
            Template.RegisterSafeType(typeof(Section), new[] { "Name", "Summary", "Items", "Icon" });
            Template.RegisterSafeType(typeof(Category), new[] { "Name", "Items" });
            Template.RegisterSafeType(typeof(Item), new[] { "TaskId", "TaskLink", "Categories", "Priority", "Summary" });
        }
Пример #21
0
        public static void ExecuteTest(string commonMark, string html, CommonMarkSettings settings = null)
        {
            if (settings == null)
            {
                settings = CommonMarkSettings.Default.Clone();
            }

            Helpers.LogValue("CommonMark", Denormalize(commonMark));
            Helpers.LogValue("Expected", Denormalize(html));

            // Arrange
            commonMark = Helpers.Normalize(commonMark);
            html       = Helpers.Normalize(html);

            string actual;

            Syntax.Block document;

            // Act
            using (var reader = new System.IO.StringReader(commonMark))
                using (var writer = new System.IO.StringWriter())
                {
                    document = CommonMarkConverter.ProcessStage1(reader, settings);
                    CommonMarkConverter.ProcessStage2(document, settings);
                    CommonMarkConverter.ProcessStage3(document, writer, settings);
                    actual = writer.ToString();
                }

            // Assert
            Helpers.LogValue("Actual", Denormalize(actual));
            actual = Helpers.Tidy(actual);
            Assert.AreEqual(Helpers.Tidy(html), actual);

            // Verify that the extendable HTML formatter returns the same result
            var settingsHtmlFormatter = settings.Clone();

            settingsHtmlFormatter.OutputDelegate = (doc, target, stngs) => new Formatters.HtmlFormatter(target, stngs).WriteDocument(doc);
            var actual2 = CommonMarkConverter.Convert(commonMark, settingsHtmlFormatter);

            Assert.AreEqual(actual, Helpers.Tidy(actual2), "HtmlFormatter returned a different result than HtmlFormatterSlim.");

            // Additionally verify that the parser included source position information.
            // This is done here to catch cases during specification tests that might not be
            // covered in SourcePositionTests.cs.
            var firstFail = document.AsEnumerable().FirstOrDefault(o => o.Inline != null && o.IsOpening && o.Inline.SourceLength <= 0);

            if (firstFail != null)
            {
                Assert.Fail("Incorrect source position: " + firstFail);
            }
        }
Пример #22
0
        public override byte[] ReadBytes()
        {
            if (CachedContent.Length == 0)
            {
                Refresh();
            }
            string text = System.Text.Encoding.UTF8.GetString(CachedContent);

            CommonMarkSettings setting = CommonMarkSettings.Default.Clone();

            setting.AdditionalFeatures = CommonMarkAdditionalFeatures.All;
            html = CommonMarkConverter.Convert(text, setting);
            return(System.Text.Encoding.UTF8.GetBytes(html));
        }
Пример #23
0
        public FlowDocument BlocksToXaml(Block block, CommonMarkSettings settings)
        {
            //_checkBoxNumber = 0;
            FlowDocument document = new FlowDocument();

            document.PagePadding = new Thickness(0);
            if (DocumentStyle != null)
            {
                document.Style = DocumentStyle;
            }

            BlocksToXamlInner(document, block, settings);

            return(document);
        }
Пример #24
0
        public MarkdownLoader(IHostingEnvironment environment)
        {
            fileProvider       = environment.ContentRootFileProvider;
            commonMarkSettings = CommonMarkSettings.Default.Clone();
            bundles            = new Dictionary <string, MarkdownBundle>();

            // Lets us resolve numbers to issue links.
            commonMarkSettings.AdditionalFeatures = CommonMarkAdditionalFeatures.PlaceholderBracket;
            commonMarkSettings.OutputDelegate     = FormatDocument;
            // May become obsolete, if we can resolve [NodaTime.LocalDateTime] to the right type link etc.
            commonMarkSettings.UriResolver = ResolveUrl;

            // TODO: Make the root location configurable
            LoadRecursive("Markdown");
        }
Пример #25
0
        /// <summary>Initializes a new instance of the <see cref="HtmlFormatter" /> class.</summary>
        /// <param name="target">The target text writer.</param>
        /// <param name="settings">The settings used when formatting the data.</param>
        /// <exception cref="ArgumentNullException">when <paramref name="target"/> is <c>null</c></exception>
        public HtmlFormatter(TextWriter target, CommonMarkSettings settings)
        {
            if (target == null)
            {
                throw new ArgumentNullException(target.ToString());
            }

            if (settings == null)
            {
                settings = CommonMarkSettings.Default;
            }

            _target   = new HtmlTextWriter(target);
            _settings = settings;
        }
Пример #26
0
        /// <summary>
        /// Initializes a new instance of <see cref="ProjbookHtmlFormatter"/>.
        /// </summary>
        /// <param name="contextName">Initializes the required <see cref="ContextName"/></param>
        /// <param name="target">Initializes the required text writer used as output.</param>
        /// <param name="settings">Initializes the required common mark settings used by the formatting.</param>
        /// <param name="sectionTitleBase">Initializes the section title base.</param>
        /// <param name="snippetDictionary">Initializes the snippet directory.</param>
        /// <param name="snippetReferencePrefix">Initializes the snippet reference prefix.</param>
        public ProjbookHtmlFormatter(string contextName, TextWriter target, CommonMarkSettings settings, int sectionTitleBase, Dictionary <Guid, Extension.Model.Snippet> snippetDictionary, string snippetReferencePrefix)
            : base(target, settings)
        {
            // Data validation
            Ensure.That(() => contextName).IsNotNullOrWhiteSpace();
            Ensure.That(target is StreamWriter).IsTrue();
            Ensure.That(() => sectionTitleBase).IsGte(0);
            Ensure.That(() => snippetDictionary).IsNotNull();
            Ensure.That(() => snippetReferencePrefix).IsNotNull();

            // Initialize
            this.ContextName            = contextName;
            this.pageBreak              = new List <PageBreakInfo>();
            this.writer                 = target as StreamWriter;
            this.sectionTitleBase       = sectionTitleBase;
            this.snippetDictionary      = snippetDictionary;
            this.snippetReferencePrefix = snippetReferencePrefix;
        }
Пример #27
0
        internal static InlineTag[] InitializeSingleCharTags(CommonMarkSettings settings)
        {
            var handleCaret = 0 != (settings.AdditionalFeatures & CommonMarkAdditionalFeatures.SuperscriptCaret);
            var handleTilde = 0 != (settings.AdditionalFeatures & CommonMarkAdditionalFeatures.SubscriptTilde);
            var handleMath = 0 != (settings.AdditionalFeatures & CommonMarkAdditionalFeatures.MathDollar);

            var t = InitializeEmphasisSingleCharTags(handleTilde);

            if (handleCaret)
                t['^'] = InlineTag.Superscript;

            if (handleTilde)
                t['~'] = InlineTag.Subscript;

            if (handleMath)
                t['$'] = InlineTag.Math;

            return t;
        }
Пример #28
0
        /// <summary>
        /// Break out of all containing lists
        /// </summary>
        private static void BreakOutOfLists(ref Block blockRef, LineInfo line, CommonMarkSettings settings)
        {
            Block container = blockRef;
            Block b = container.Top;

            // find first containing list:
            while (b != null && b.Tag != BlockTag.List)
                b = b.LastChild;

            if (b != null)
            {
                while (container != null && container != b)
                {
                    Finalize(container, line, settings);
                    container = container.Parent;
                }

                Finalize(b, line, settings);
                blockRef = b.Parent;
            }
        }
Пример #29
0
        public static void ExecuteTest(string commonMark, string html, CommonMarkSettings settings = null)
        {
            if (settings == null)
                settings = CommonMarkSettings.Default.Clone();

            Helpers.LogValue("CommonMark", Denormalize(commonMark));
            Helpers.LogValue("Expected", Denormalize(html));

            // Arrange
            commonMark = Helpers.Normalize(commonMark);
            html = Helpers.Normalize(html);
            
            string actual;
            Syntax.Block document;

            // Act
            using (var reader = new System.IO.StringReader(commonMark))
            using (var writer = new System.IO.StringWriter())
            {
                document = CommonMarkConverter.ProcessStage1(reader, settings);
                CommonMarkConverter.ProcessStage2(document, settings);
                CommonMarkConverter.ProcessStage3(document, writer, settings);
                actual = writer.ToString();
            }

            // Assert
            Helpers.LogValue("Actual", Denormalize(actual));
            actual = Helpers.Tidy(actual);
            Assert.AreEqual(Helpers.Tidy(html), actual);

            // Verify that the parser included source position information.
            // This is done here to catch cases during specification tests that might not be 
            // covered in SourcePositionTests.cs.
            var firstFail = document.AsEnumerable().FirstOrDefault(o => o.Inline != null && o.IsOpening && o.Inline.SourceLength <= 0);
            if (firstFail != null)
            {
                Assert.Fail("Incorrect source position: " + firstFail);
            }
        }
Пример #30
0
        public static void ExecuteTest(string commonMark, string html, CommonMarkSettings settings = null)
        {
            Helpers.LogValue("CommonMark", Denormalize(commonMark));
            Helpers.LogValue("Expected", Denormalize(html));

            // Arrange
            commonMark = Helpers.Normalize(commonMark);
            html       = Helpers.Normalize(html);

            string actual;

            Syntax.Block document;

            // Act
            using (var reader = new System.IO.StringReader(commonMark))
                using (var writer = new System.IO.StringWriter())
                {
                    document = CommonMarkConverter.ProcessStage1(reader, settings);
                    CommonMarkConverter.ProcessStage2(document, settings);
                    CommonMarkConverter.ProcessStage3(document, writer, settings);
                    actual = writer.ToString();
                }

            // Assert
            Helpers.LogValue("Actual", Denormalize(actual));
            Assert.AreEqual(Helpers.Tidy(html), Helpers.Tidy(actual));

            // Additionally verify that the parser included source position information.
            // This is done here to catch cases during specification tests that might not be
            // covered in SourcePositionTests.cs.
            var firstFail = document.AsEnumerable().FirstOrDefault(o => o.Inline != null && o.IsOpening && o.Inline.SourceLength <= 0);

            if (firstFail != null)
            {
                Assert.Fail("Incorrect source position: " + firstFail);
            }
        }
Пример #31
0
        /// <summary>
        /// Adds a new reference to the dictionary, if the label does not already exist there.
        /// Assumes that the length of the label does not exceed <see cref="Reference.MaximumReferenceLabelLength"/>.
        /// </summary>
        private static void AddReference(Dictionary<string, Reference> refmap, StringPart label, string url, string title, CommonMarkSettings settings)
        {
            var normalizedLabel = NormalizeReference(label, settings);
            if (refmap.ContainsKey(normalizedLabel))
                return;

            refmap.Add(normalizedLabel, new Reference(normalizedLabel, url, title));
        }
Пример #32
0
        /// <summary>
        /// Writes the inline list to the given parent as HTML code.
        /// </summary>
        private void InlinesToXaml(IAddChild parent, Inline inline, CommonMarkSettings settings, Stack <InlineStackEntry> stack)
        {
            var  uriResolver     = settings.UriResolver;
            bool withinLink      = false;
            bool stackWithinLink = false;
            bool trackPositions  = settings.TrackSourcePosition;

            IAddChild blockParent = parent;

            if (blockParent is ListItem || blockParent is Section || blockParent is TableCell)
            {
                Paragraph p = new Paragraph();
                blockParent.AddChild(p);
                blockParent = p;
            }

            while (inline != null)
            {
                var       visitChildren = false;
                IAddChild lastParent    = null;

                switch (inline.Tag)
                {
                case InlineTag.String:
                    //if (inline.LiteralContent.StartsWith("[ ]") || inline.LiteralContent.StartsWith("[x]"))
                    //{
                    //	CheckBox bt = new CheckBox
                    //	{
                    //		IsChecked = inline.LiteralContent.Contains("[x]"),
                    //		Content = inline.LiteralContent.Substring(2),
                    //		Tag = _checkBoxNumber
                    //	};
                    //	bt.CommandParameter = bt;
                    //	bt.Command = CheckBoxCheckedCommand;
                    //	bt.Style = TodoCheckBoxStyle;
                    //	blockParent.AddChild(new BlockUIContainer(bt));
                    //	_checkBoxNumber++;
                    //}
                    //else
                    blockParent.AddText(inline.LiteralContent);
                    break;

                case InlineTag.LineBreak:
                    blockParent.AddChild(new LineBreak());
                    break;

                case InlineTag.SoftBreak:
                    if (settings.RenderSoftLineBreaksAsLineBreaks)
                    {
                        blockParent.AddChild(new LineBreak());
                    }
                    break;

                case InlineTag.Code:

                    Span codeSpan = new Span(new Run(inline.LiteralContent));
                    if (InlineCodeStyle != null)
                    {
                        codeSpan.Style = InlineCodeStyle;
                    }

                    blockParent.AddChild(codeSpan);

                    break;

                case InlineTag.RawHtml:
                    // cannot output source position for HTML blocks
                    blockParent.AddText(inline.LiteralContent);
                    break;

                case InlineTag.Link:
                    if (withinLink)
                    {
                        //parent.Write('[');
                        //stackLiteral = "]";
                        stackWithinLink = true;
                        visitChildren   = true;
                    }
                    else
                    {
                        Hyperlink hyperlink = new Hyperlink();

                        if (LinkStyle != null)
                        {
                            hyperlink.Style = LinkStyle;
                        }

                        string url = inline.TargetUrl;
                        if (uriResolver != null)
                        {
                            url = uriResolver(inline.TargetUrl);
                        }

                        hyperlink.CommandParameter = url;
                        if (Uri.IsWellFormedUriString(url, UriKind.Absolute))
                        {
                            hyperlink.NavigateUri      = new Uri(url);
                            hyperlink.RequestNavigate += (sender, e) =>
                            {
                                System.Diagnostics.Process.Start(e.Uri.ToString());
                            };
                        }
                        else
                        {
                            hyperlink.Command = HyperlinkCommand;
                        }

                        if (inline.LiteralContent.Length > 0)
                        {
                            hyperlink.ToolTip = inline.LiteralContent;
                        }

                        if (trackPositions)
                        {
                            PrintPosition(hyperlink, inline);
                        }

                        if (!(blockParent is Hyperlink))
                        {
                            blockParent.AddChild(hyperlink);
                        }

                        lastParent  = blockParent;
                        blockParent = hyperlink;

                        visitChildren   = true;
                        stackWithinLink = true;
                    }
                    break;

                case InlineTag.Image:
                    HandleImage(inline, parent);

                    break;

                case InlineTag.Strong:
                    Bold bold = new Bold();
                    blockParent.AddChild(bold);
                    lastParent  = blockParent;
                    blockParent = bold;

                    if (trackPositions)
                    {
                        PrintPosition(bold, inline);
                    }

                    stackWithinLink = withinLink;
                    visitChildren   = true;
                    break;

                case InlineTag.Emphasis:
                    Italic italic = new Italic();
                    blockParent.AddChild(italic);
                    lastParent  = blockParent;
                    blockParent = italic;

                    if (trackPositions)
                    {
                        PrintPosition(italic, inline);
                    }

                    visitChildren   = true;
                    stackWithinLink = withinLink;
                    break;

                case InlineTag.Strikethrough:
                    Span strikethroughSpan = new Span();
                    strikethroughSpan.TextDecorations = TextDecorations.Strikethrough;

                    blockParent.AddChild(strikethroughSpan);
                    lastParent  = blockParent;
                    blockParent = strikethroughSpan;

                    if (trackPositions)
                    {
                        PrintPosition(strikethroughSpan, inline);
                    }

                    visitChildren   = true;
                    stackWithinLink = withinLink;
                    break;

                case InlineTag.Placeholder:
                    // the slim formatter will treat placeholders like literals, without applying any further processing

                    //if (blockParent is ListItem)
                    //	blockParent.AddChild(new Paragraph(new Run("Placeholder")));
                    //else
                    //	blockParent.AddText("Placeholder");

                    //visitChildren = false;

                    //TODO: Handle todo-list items here
                    break;

                default:
                    throw new CommonMarkException("Inline type " + inline.Tag + " is not supported.", inline);
                }

                if (visitChildren)
                {
                    stack.Push(new InlineStackEntry(lastParent, inline.NextSibling, withinLink));

                    withinLink = stackWithinLink;
                    inline     = inline.FirstChild;
                }
                else if (inline.NextSibling != null)
                {
                    inline = inline.NextSibling;
                }
                else
                {
                    inline = null;
                }

                while (inline == null && stack.Count > 0)
                {
                    var entry = stack.Pop();

                    blockParent = entry.Parent;
                    inline      = entry.Target;
                    withinLink  = entry.IsWithinLink;
                }
            }
        }
Пример #33
0
        public static void Finalize(Block b, LineInfo line, CommonMarkSettings settings)
        {
            // don't do anything if the block is already closed
            if (!b.IsOpen)
                return;

            b.IsOpen = false;

            if (line.IsTrackingPositions)
            {
                // (b.SourcePosition >= line.LineOffset) determines if the block started on this line.
                if (b.SourcePosition >= line.LineOffset && line.Line != null)
                    b.SourceLastPosition = line.CalculateOrigin(line.Line.Length, false);
                else
                    b.SourceLastPosition = line.CalculateOrigin(0, false);
            }

#pragma warning disable 0618
            b.EndLine = (line.LineNumber > b.StartLine) ? line.LineNumber - 1 : line.LineNumber;
#pragma warning restore 0618

            switch (b.Tag)
            {
                case BlockTag.Paragraph:
                    var sc = b.StringContent;
                    if (!sc.StartsWith('['))
                        break;

                    var subj = new Subject(b.Top.ReferenceMap);
                    sc.FillSubject(subj);
                    var origPos = subj.Position;
                    while (subj.Position < subj.Buffer.Length 
                        && subj.Buffer[subj.Position] == '[' 
                        && 0 != InlineMethods.ParseReference(subj, settings))
                    {
                    }

                    if (subj.Position != origPos)
                    {
                        sc.Replace(subj.Buffer, subj.Position, subj.Buffer.Length - subj.Position);

                        if (sc.PositionTracker != null)
                            sc.PositionTracker.AddBlockOffset(subj.Position - origPos);

                        if (Utilities.IsFirstLineBlank(subj.Buffer, subj.Position))
                            b.Tag = BlockTag.ReferenceDefinition;
                    }

                    break;

                case BlockTag.IndentedCode:
                    b.StringContent.RemoveTrailingBlankLines();
                    break;

                case BlockTag.FencedCode:
                case BlockTag.CustomContainer:
                    // first line of contents becomes info
                    var firstlinelen = b.StringContent.IndexOf('\n') + 1;
                    b.FencedCodeData.Info = InlineMethods.Unescape(b.StringContent.TakeFromStart(firstlinelen, true).Trim());
                    break;

                case BlockTag.List: // determine tight/loose status
                    b.ListData.IsTight = true; // tight by default
                    var item = b.FirstChild;
                    Block subitem;

                    while (item != null)
                    {
                        // check for non-final non-empty list item ending with blank line:
                        if (item.IsLastLineBlank && item.NextSibling != null)
                        {
                            b.ListData.IsTight = false;
                            break;
                        }

                        // recurse into children of list item, to see if there are spaces between them:
                        subitem = item.FirstChild;
                        while (subitem != null)
                        {
                            if (EndsWithBlankLine(subitem) && (item.NextSibling != null || subitem.NextSibling != null))
                            {
                                b.ListData.IsTight = false;
                                break;
                            }

                            subitem = subitem.NextSibling;
                        }

                        if (!b.ListData.IsTight)
                            break;

                        item = item.NextSibling;
                    }

                    break;
            }
        }
Пример #34
0
        private void WriteGitHubHeadingIds(HtmlTextWriter writer, Inline inline, CommonMarkSettings settings, Stack<InlineStackEntry> stack) {
            using (var tempWriter = new System.IO.StringWriter()) {
                var tempWrapper = new HtmlTextWriter(tempWriter);
                var tempStringBuilder = new StringBuilder();
                InlinesToPlainText(tempWrapper, inline, stack);
                string plaintextContent = tempWriter.ToString();

                // Normalize plaintext content according to GitHub ID rules
                plaintextContent = new Regex(@"[^\w\-\ ]").Replace(plaintextContent, "").Replace(" ", "-");
                for (int c = 0; c < plaintextContent.Length; c++) {
                    if (plaintextContent[c] >= 'A' && plaintextContent[c] <= 'Z')
                        tempStringBuilder.Append((char)(plaintextContent[c] + 32));
                    else
                        tempStringBuilder.Append(plaintextContent[c]);
                }
                plaintextContent = tempStringBuilder.ToString();
                string unique = "";
                if (GitHubHeaderIdCounts.ContainsKey(plaintextContent))
                    unique = "-" + ++GitHubHeaderIdCounts[plaintextContent];
                else
                    GitHubHeaderIdCounts[plaintextContent] = 0;

                writer.WriteConstant(string.Format(@"<a id=""user-content-{0}{1}"" class=""anchor"" href=""#user-content-{0}{1}"" aria-hidden=""true""><svg class=""octicon octicon-link"" aria-hidden=""true"" height=""16"" role=""img"" version=""1.1"" viewBox=""0 0 16 16"" width=""16""><path d=""M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z""></path></svg></a>",
                    plaintextContent, unique));
            }
        }
Пример #35
0
        /// <summary>
        /// Writes the inline list to the given writer as HTML code. 
        /// </summary>
        private static void InlinesToHtml(HtmlTextWriter writer, Inline inline, CommonMarkSettings settings, Stack<InlineStackEntry> stack)
        {
            var uriResolver = settings.UriResolver;
            bool withinLink = false;
            bool stackWithinLink = false;
            bool visitChildren;
            bool trackPositions = settings.TrackSourcePosition;
            string stackLiteral = null;

            while (inline != null)
            {
                visitChildren = false;

                switch (inline.Tag)
                {
                    case InlineTag.String:
                        if (trackPositions)
                        {
                            writer.WriteConstant("<span");
                            PrintPosition(writer, inline);
                            writer.Write('>');
                            EscapeHtml(inline.LiteralContentValue, writer);
                            writer.WriteConstant("</span>");
                        }
                        else
                        {
                            EscapeHtml(inline.LiteralContentValue, writer);
                        }

                        break;

                    case InlineTag.LineBreak:
                        writer.WriteLineConstant("<br />");
                        break;

                    case InlineTag.SoftBreak:
                        if (settings.RenderSoftLineBreaksAsLineBreaks)
                            writer.WriteLineConstant("<br />");
                        else
                            writer.WriteLine();
                        break;

                    case InlineTag.Code:
                        writer.WriteConstant("<code");
                        if (trackPositions) PrintPosition(writer, inline);
                        writer.Write('>');
                        EscapeHtml(inline.LiteralContentValue, writer);
                        writer.WriteConstant("</code>");
                        break;

                    case InlineTag.RawHtml:
                        // cannot output source position for HTML blocks
                        writer.Write(inline.LiteralContentValue);
                        break;

                    case InlineTag.Link:
                        if (withinLink)
                        {
                            writer.Write('[');
                            stackLiteral = "]";
                            stackWithinLink = true;
                            visitChildren = true;
                        }
                        else
                        {
                            writer.WriteConstant("<a href=\"");
                            if (uriResolver != null)
                                EscapeUrl(uriResolver(inline.TargetUrl), writer);
                            else
                                EscapeUrl(inline.TargetUrl, writer);

                            writer.Write('\"');
                            if (inline.LiteralContentValue.Length > 0)
                            {
                                writer.WriteConstant(" title=\"");
                                EscapeHtml(inline.LiteralContentValue, writer);
                                writer.Write('\"');
                            }

                            if (trackPositions) PrintPosition(writer, inline);

                            writer.Write('>');

                            visitChildren = true;
                            stackWithinLink = true;
                            stackLiteral = "</a>";
                        }
                        break;

                    case InlineTag.Image:
                        writer.WriteConstant("<img src=\"");
                        if (uriResolver != null)
                            EscapeUrl(uriResolver(inline.TargetUrl), writer);
                        else
                            EscapeUrl(inline.TargetUrl, writer);

                        writer.WriteConstant("\" alt=\"");
                        InlinesToPlainText(writer, inline.FirstChild, stack);
                        writer.Write('\"');
                        if (inline.LiteralContentValue.Length > 0)
                        {
                            writer.WriteConstant(" title=\"");
                            EscapeHtml(inline.LiteralContentValue, writer);
                            writer.Write('\"');
                        }

                        if (trackPositions) PrintPosition(writer, inline);
                        writer.WriteConstant(" />");

                        break;

                    case InlineTag.Strong:
                        writer.WriteConstant("<strong");
                        if (trackPositions) PrintPosition(writer, inline);
                        writer.Write('>');
                        stackLiteral = "</strong>";
                        stackWithinLink = withinLink;
                        visitChildren = true;
                        break;

                    case InlineTag.Emphasis:
                        writer.WriteConstant("<em");
                        if (trackPositions) PrintPosition(writer, inline);
                        writer.Write('>');
                        stackLiteral = "</em>";
                        visitChildren = true;
                        stackWithinLink = withinLink;
                        break;

                    case InlineTag.Strikethrough:
                        writer.WriteConstant("<del");
                        if (trackPositions) PrintPosition(writer, inline);
                        writer.Write('>');
                        stackLiteral = "</del>";
                        visitChildren = true;
                        stackWithinLink = withinLink;
                        break;

                    default:
                        throw new CommonMarkException("Inline type " + inline.Tag + " is not supported.", inline);
                }

                if (visitChildren)
                {
                    stack.Push(new InlineStackEntry(stackLiteral, inline.NextSibling, withinLink));

                    withinLink = stackWithinLink;
                    inline = inline.FirstChild;
                }
                else if (inline.NextSibling != null)
                {
                    inline = inline.NextSibling;
                }
                else
                {
                    inline = null;
                }

                while (inline == null && stack.Count > 0)
                {
                    var entry = stack.Pop();
                    writer.WriteConstant(entry.Literal);
                    inline = entry.Target;
                    withinLink = entry.IsWithinLink;
                }
            }
        }
 public ExternalLinkFormatter(System.IO.TextWriter target, CommonMarkSettings settings)
     : base(target, settings)
 {
 }
Пример #37
0
        private static Inline HandleRightSquareBracket(Subject subj, CommonMarkSettings settings)
        {
            // move past ']'
            subj.Position++;

            bool canClose;
            var istack = InlineStack.FindMatchingOpener(subj.LastPendingInline, InlineStack.InlineStackPriority.Links, '[', out canClose);

            if (istack != null)
            {
                // if the opener is "inactive" then it means that there was a nested link
                if (istack.DelimeterCount == -1)
                {
                    InlineStack.RemoveStackEntry(istack, subj, istack, settings.InlineParserParameters);
                    return new Inline("]", subj.Position - 1, subj.Position);
                }

                var endpos = subj.Position;

                // try parsing details for '[foo](/url "title")' or '[foo][bar]'
                var details = ParseLinkDetails(subj, settings);

                // try lookup of the brackets themselves
                if (details == null || details == Reference.SelfReference)
                {
                    var startpos = istack.StartPosition;
                    var label = new StringPart(subj.Buffer, startpos, endpos - startpos - 1);

                    details = LookupReference(subj.ReferenceMap, label, settings);
                }

                if (details == Reference.InvalidReference)
                    details = null;

                MatchSquareBracketStack(istack, subj, details, settings.InlineParserParameters);
                return null;
            }

            var inlText = new Inline("]", subj.Position - 1, subj.Position);

            if (canClose)
            {
                // note that the current implementation will not work if there are other inlines with priority
                // higher than Links.
                // to fix this the parsed link details should be added to the closer element in the stack.

                throw new NotSupportedException("It is not supported to have inline stack priority higher than Links.");

                ////istack = new InlineStack();
                ////istack.Delimeter = '[';
                ////istack.StartingInline = inlText;
                ////istack.StartPosition = subj.Position;
                ////istack.Priority = InlineStack.InlineStackPriority.Links;
                ////istack.Flags = InlineStack.InlineStackFlags.Closer;

                ////InlineStack.AppendStackEntry(istack, subj);
            }

            return inlText;
        }
Пример #38
0
            /// <summary>
            /// Convert a block list to HTML.  Returns 0 on success, and sets result.
            /// </summary>
            /// <remarks><para>Orig: blocks_to_html.</para></remarks>
            public static void BlocksToHtml(System.IO.TextWriter writer, Block block, CommonMarkSettings settings, ISymbol documentedSymbol)
            {
                var wrapper = new DocumentationCommentTextWriter(writer);

                BlocksToHtmlInner(wrapper, block, settings, documentedSymbol);
            }
Пример #39
0
        private static Inline HandleLeftSquareBracket(Subject subj, bool isImage, CommonMarkSettings settings)
        {
            Inline inlText;
            
            if (isImage)
            {
                inlText = new Inline("![", subj.Position - 1, subj.Position + 1);
            }
            else
            {
                inlText = new Inline("[", subj.Position, subj.Position + 1);
            }

            // move past the '['
            subj.Position++;

            var istack = new InlineStack();
            istack.Delimeter = '[';
            istack.StartingInline = inlText;
            istack.StartPosition = subj.Position;
            istack.Priority = InlineStack.InlineStackPriority.Links;
            istack.Flags = InlineStack.InlineStackFlags.Opener | (isImage ? InlineStack.InlineStackFlags.ImageLink : InlineStack.InlineStackFlags.None);

            InlineStack.AppendStackEntry(istack, subj);

            return inlText;
        }
Пример #40
0
        /// <summary>
        /// Write the block data to the given writer.
        /// </summary>
        public static void PrintBlocks(TextWriter writer, Block block, CommonMarkSettings settings)
        {
            int indent = 0;
            var stack = new Stack<BlockStackEntry>();
            var inlineStack = new Stack<InlineStackEntry>();
            var buffer = new StringBuilder();
            var trackPositions = settings.TrackSourcePosition;

            while (block != null)
            {
                writer.Write(new string(' ', indent));

                switch (block.Tag)
                {
                    case BlockTag.Document:
                        writer.Write("document");
                        PrintPosition(trackPositions, writer, block);
                        break;

                    case BlockTag.BlockQuote:
                        writer.Write("block_quote");
                        PrintPosition(trackPositions, writer, block);
                        break;

                    case BlockTag.ListItem:
                        writer.Write("list_item");
                        PrintPosition(trackPositions, writer, block);
                        break;

                    case BlockTag.List:
                        writer.Write("list");
                        PrintPosition(trackPositions, writer, block);

                        var data = block.ListData;
                        if (data.ListType == ListType.Ordered)
                        {
                            writer.Write(" (type=ordered tight={0} start={1} delim={2})",
                                 data.IsTight,
                                 data.Start,
                                 data.Delimiter);
                        }
                        else
                        {
                            writer.Write("(type=bullet tight={0} bullet_char={1})",
                                 data.IsTight,
                                 data.BulletChar);
                        }
                        break;

                    case BlockTag.AtxHeader:
                        writer.Write("atx_header");
                        PrintPosition(trackPositions, writer, block);
                        writer.Write(" (level={0})", block.HeaderLevel);
                        break;

                    case BlockTag.SETextHeader:
                        writer.Write("setext_header");
                        PrintPosition(trackPositions, writer, block);
                        writer.Write(" (level={0})", block.HeaderLevel);
                        break;

                    case BlockTag.Paragraph:
                        writer.Write("paragraph");
                        PrintPosition(trackPositions, writer, block);
                        break;

                    case BlockTag.HorizontalRuler:
                        writer.Write("hrule");
                        PrintPosition(trackPositions, writer, block);
                        break;

                    case BlockTag.IndentedCode:
                        writer.Write("indented_code {0}", format_str(block.StringContent.ToString(buffer), buffer));
                        PrintPosition(trackPositions, writer, block);
                        writer.Write(' ');
                        writer.Write(format_str(block.StringContent.ToString(buffer), buffer));
                        break;

                    case BlockTag.FencedCode:
                        writer.Write("fenced_code");
                        PrintPosition(trackPositions, writer, block);
                        writer.Write(" length={0} info={1} {2}",
                               block.FencedCodeData.FenceLength,
                               format_str(block.FencedCodeData.Info, buffer),
                               format_str(block.StringContent.ToString(buffer), buffer));
                        break;

                    case BlockTag.CustomContainer:
                        writer.Write("custom_container");
                        PrintPosition(trackPositions, writer, block);
                        writer.Write(" length={0} info={1} {2}",
                               block.FencedCodeData.FenceLength,
                               format_str(block.FencedCodeData.Info, buffer),
                               format_str(block.StringContent.ToString(buffer), buffer));
                        break;

                    case BlockTag.HtmlBlock:
                        writer.Write("html_block");
                        PrintPosition(trackPositions, writer, block);
                        writer.Write(' ');
                        writer.Write(format_str(block.StringContent.ToString(buffer), buffer));
                        break;

                    case BlockTag.ReferenceDefinition:
                        writer.Write("reference_def");
                        PrintPosition(trackPositions, writer, block);
                        break;

                    default:
                        throw new CommonMarkException("Block type " + block.Tag + " is not supported.", block);
                }

                writer.WriteLine();

                if (block.InlineContent != null)
                {
                    PrintInlines(writer, block.InlineContent, indent + 2, inlineStack, buffer, trackPositions);
                }

                if (block.FirstChild != null)
                {
                    if (block.NextSibling != null)
                        stack.Push(new BlockStackEntry(indent, block.NextSibling));

                    indent += 2;
                    block = block.FirstChild;
                }
                else if (block.NextSibling != null)
                {
                    block = block.NextSibling;
                }
                else if (stack.Count > 0)
                {
                    var entry = stack.Pop();
                    indent = entry.Indent;
                    block = entry.Target;
                }
                else
                {
                    block = null;
                }
            }
        }
Пример #41
0
 private static Inline HandleLeftSquareBracket(Subject subj, CommonMarkSettings settings)
 {
     return HandleLeftSquareBracket(subj, false, settings);
 }
Пример #42
0
 private static Inline HandleExclamation(Subject subj, CommonMarkSettings settings)
 {
     subj.Position++;
     if (peek_char(subj) == '[')
         return HandleLeftSquareBracket(subj, true, settings);
     else
         return new Inline("!", subj.Position - 1, subj.Position);
 }
Пример #43
0
        /// <summary>
        /// Adds a new block as child of another. Return the child.
        /// </summary>
        /// <remarks>Original: add_child</remarks>
        public static Block CreateChildBlock(Block parent, LineInfo line, BlockTag blockType, int startColumn, CommonMarkSettings settings)
        {
            // if 'parent' isn't the kind of block that can accept this child,
            // then back up til we hit a block that can.
            while (!CanContain(parent.Tag, blockType))
            {
                Finalize(parent, line, settings);
                parent = parent.Parent;
            }

            var startPosition = line.IsTrackingPositions ? line.CalculateOrigin(startColumn, true) : line.LineOffset;
#pragma warning disable 0618
            Block child = new Block(blockType, line.LineNumber, startColumn + 1, startPosition);
#pragma warning restore 0618
            child.Parent = parent;
            child.Top = parent.Top;

            var lastChild = parent.LastChild;
            if (lastChild != null)
            {
                lastChild.NextSibling = child;
#pragma warning disable 0618
                child.Previous = lastChild;
#pragma warning restore 0618
            }
            else
            {
                parent.FirstChild = child;
            }

            parent.LastChild = child;
            return child;
        }
Пример #44
0
        private void WriteTable(Block table, IAddChild parent, CommonMarkSettings settings, Stack <InlineStackEntry> stack)
        {
            if ((settings.AdditionalFeatures & CommonMarkAdditionalFeatures.GithubStyleTables) == 0)
            {
                throw new CommonMarkException("Table encountered in AST, but GithubStyleTables are not enabled");
            }

            var header   = table.FirstChild;
            var firstRow = table.FirstChild.NextSibling;

            Table t = new Table();

            parent.AddChild(t);

            if (TableStyle != null)
            {
                t.Style = TableStyle;
            }

            var tableHeadRowGroup = new TableRowGroup();

            t.RowGroups.Add(tableHeadRowGroup);
            TableRow headRow = new TableRow();

            if (TableHeadStyle != null)
            {
                headRow.Style = TableHeadStyle;
            }
            tableHeadRowGroup.Rows.Add(headRow);

            var numHeadings = 0;

            var curHeaderCell = header.FirstChild;

            while (curHeaderCell != null)
            {
                if (numHeadings >= table.TableHeaderAlignments.Length)
                {
                    break;
                }

                var alignment = table.TableHeaderAlignments[numHeadings];

                numHeadings++;

                TableCell cell = new TableCell();
                if (TableCellStyle != null)
                {
                    cell.Style = TableCellStyle;
                }

                InlinesToXaml(cell, curHeaderCell.InlineContent, settings, stack);

                if (alignment != TableHeaderAlignment.None)
                {
                    switch (alignment)
                    {
                    case TableHeaderAlignment.Center: cell.TextAlignment = TextAlignment.Center; break;

                    case TableHeaderAlignment.Left: cell.TextAlignment = TextAlignment.Left; break;

                    case TableHeaderAlignment.Right: cell.TextAlignment = TextAlignment.Right; break;

                    default: throw new CommonMarkException("Unexpected TableHeaderAlignment [" + alignment + "]");
                    }
                }

                headRow.Cells.Add(cell);

                curHeaderCell = curHeaderCell.NextSibling;
            }

            var tableBodyRowGroup = new TableRowGroup();

            t.RowGroups.Add(tableBodyRowGroup);

            var curRow = firstRow;

            while (curRow != null)
            {
                TableRow row = new TableRow();
                if (TableRowStyle != null)
                {
                    row.Style = TableRowStyle;
                }

                tableBodyRowGroup.Rows.Add(row);

                var curRowCell = curRow.FirstChild;

                var numCells = 0;

                while (curRowCell != null && numCells < numHeadings)
                {
                    var alignment = table.TableHeaderAlignments[numCells];

                    numCells++;

                    TableCell cell = new TableCell();
                    if (TableCellStyle != null)
                    {
                        cell.Style = TableCellStyle;
                    }

                    row.Cells.Add(cell);

                    if (alignment != TableHeaderAlignment.None)
                    {
                        switch (alignment)
                        {
                        case TableHeaderAlignment.Center: cell.TextAlignment = TextAlignment.Center; break;

                        case TableHeaderAlignment.Left: cell.TextAlignment = TextAlignment.Left; break;

                        case TableHeaderAlignment.Right: cell.TextAlignment = TextAlignment.Right; break;

                        default: throw new CommonMarkException("Unexpected TableHeaderAlignment [" + alignment + "]");
                        }
                    }

                    InlinesToXaml(cell, curRowCell.InlineContent, settings, stack);

                    curRowCell = curRowCell.NextSibling;
                }

                while (numCells < numHeadings)
                {
                    numCells++;

                    TableCell cell = new TableCell();
                    if (TableCellStyle != null)
                    {
                        cell.Style = TableCellStyle;
                    }

                    row.Cells.Add(cell);
                }

                curRow = curRow.NextSibling;
            }
        }
Пример #45
0
        /// <summary>
        /// Walk through the block, its children and siblings, parsing string content into inline content where appropriate.
        /// </summary>
        /// <param name="block">The document level block from which to start the processing.</param>
        /// <param name="refmap">The reference mapping used when parsing links.</param>
        /// <param name="settings">The settings that influence how the inline parsing is performed.</param>
        public static void ProcessInlines(Block block, Dictionary<string, Reference> refmap, CommonMarkSettings settings)
        {
            Stack<Inline> inlineStack = null;
            var stack = new Stack<Block>();
            var subj = new Subject(refmap);

            StringContent sc;
            int delta;

            while (block != null)
            {
                var tag = block.Tag;

                var parseEmphasisInIndentedCode =
                    tag == BlockTag.IndentedCode
                    && 0 != (settings.AdditionalFeatures & CommonMarkAdditionalFeatures.EmphasisInIndentedCode);
                if (tag == BlockTag.Paragraph || tag == BlockTag.AtxHeader || tag == BlockTag.SETextHeader || tag == BlockTag.CustomContainer || parseEmphasisInIndentedCode)
                {
                    sc = block.StringContent;
                    if (sc != null)
                    {
                        sc.FillSubject(subj);
                        delta = subj.Position;

                        var inlineParameters = parseEmphasisInIndentedCode
                            ? settings.EmphasisInlineParserParameters
                            : settings.InlineParserParameters;
                        block.InlineContent = InlineMethods.parse_inlines(subj, refmap, inlineParameters);
                        block.StringContent = null;

                        if (sc.PositionTracker != null)
                        {
                            sc.PositionTracker.AddBlockOffset(-delta);
                            AdjustInlineSourcePosition(block.InlineContent, sc.PositionTracker, ref inlineStack);
                        }
                    }
                }

                if (block.FirstChild != null)
                {
                    if (block.NextSibling != null)
                        stack.Push(block.NextSibling);

                    block = block.FirstChild;
                }
                else if (block.NextSibling != null)
                {
                    block = block.NextSibling;
                }
                else if (stack.Count > 0)
                {
                    block = stack.Pop();
                }
                else
                {
                    block = null;
                }
            }
        }
Пример #46
0
            private static void BlocksToHtmlInner(DocumentationCommentTextWriter writer, Block block, CommonMarkSettings settings, ISymbol documentedSymbol)
            {
                var    stack       = new Stack <BlockStackEntry>();
                var    inlineStack = new Stack <InlineStackEntry>();
                bool   visitChildren;
                string stackLiteral = null;
                bool   stackTight   = false;
                bool   tight        = false;
                int    x;

                while (block != null)
                {
                    visitChildren = false;

                    switch (block.Tag)
                    {
                    case BlockTag.Document:
                        stackLiteral  = null;
                        stackTight    = false;
                        visitChildren = true;
                        break;

                    case BlockTag.Paragraph:
                        if (tight)
                        {
                            InlinesToHtml(writer, block.InlineContent, settings, documentedSymbol, inlineStack);
                        }
                        else
                        {
                            writer.EnsureLine();
                            writer.WriteConstant("<para>");
                            InlinesToHtml(writer, block.InlineContent, settings, documentedSymbol, inlineStack);
                            writer.WriteLineConstant("</para>");
                        }

                        break;

                    case BlockTag.BlockQuote:
                        writer.EnsureLine();
                        writer.WriteLineConstant("<note>");

                        stackLiteral  = "</note>";
                        stackTight    = false;
                        visitChildren = true;
                        break;

                    case BlockTag.ListItem:
                        writer.EnsureLine();
                        writer.WriteConstant("<item><description>");

                        stackLiteral  = "</description></item>";
                        stackTight    = tight;
                        visitChildren = true;
                        break;

                    case BlockTag.List:
                        // make sure a list starts at the beginning of the line:
                        writer.EnsureLine();
                        var data = block.ListData;
                        writer.WriteConstant(data.ListType == ListType.Bullet ? "<list type=\"bullet\"" : "<list type=\"number\"");
                        if (data.Start != 1)
                        {
                            writer.WriteConstant(" start=\"");
                            writer.WriteConstant(data.Start.ToString(System.Globalization.CultureInfo.InvariantCulture));
                            writer.Write('\"');
                        }

                        writer.WriteLineConstant(">");

                        stackLiteral  = "</list>";
                        stackTight    = data.IsTight;
                        visitChildren = true;
                        break;

                    case BlockTag.AtxHeading:
                    case BlockTag.SetextHeading:
                        writer.EnsureLine();

                        x = block.Heading.Level;
                        writer.WriteConstant(x > 0 && x < 7 ? HeaderOpenerTags[x - 1] : "<h" + x.ToString(CultureInfo.InvariantCulture) + ">");
                        InlinesToHtml(writer, block.InlineContent, settings, documentedSymbol, inlineStack);
                        writer.WriteLineConstant(x > 0 && x < 7 ? HeaderCloserTags[x - 1] : "</h" + x.ToString(CultureInfo.InvariantCulture) + ">");
                        break;

                    case BlockTag.IndentedCode:
                        writer.EnsureLine();
                        writer.WriteConstant("<code>");
                        EscapeHtml(block.StringContent, writer);
                        writer.WriteLineConstant("</code>");
                        break;

                    case BlockTag.FencedCode:
                        writer.EnsureLine();
                        writer.WriteConstant("<code");
                        var info = block.FencedCodeData.Info;
                        if (info != null && info.Length > 0)
                        {
                            x = info.IndexOf(' ');
                            if (x == -1)
                            {
                                x = info.Length;
                            }

                            writer.WriteConstant(" language=\"");
                            EscapeHtml(info.Substring(0, x), writer);
                            writer.Write('\"');
                        }

                        writer.Write('>');
                        writer.WriteLine();
                        EscapeHtml(block.StringContent, writer);
                        writer.WriteLineConstant("</code>");
                        break;

                    case BlockTag.HtmlBlock:
                        writer.Write(block.StringContent.ToString(new StringBuilder()));
                        break;

                    case BlockTag.ThematicBreak:
                        writer.WriteLineConstant("<hr />");
                        break;

                    case BlockTag.ReferenceDefinition:
                        break;

                    default:
                        throw new CommonMarkException("Block type " + block.Tag + " is not supported.", block);
                    }

                    if (visitChildren)
                    {
                        stack.Push(new BlockStackEntry(stackLiteral, block.NextSibling, tight));

                        tight = stackTight;
                        block = block.FirstChild;
                    }
                    else if (block.NextSibling != null)
                    {
                        block = block.NextSibling;
                    }
                    else
                    {
                        block = null;
                    }

                    while (block == null && stack.Count > 0)
                    {
                        var entry = stack.Pop();

                        writer.WriteLineConstant(entry.Literal);
                        tight = entry.IsTight;
                        block = entry.Target;
                    }
                }
            }
Пример #47
0
        // Parse a link or the link portion of an image, or return a fallback.
        static Reference ParseLinkDetails(Subject subj, CommonMarkSettings settings)
        {
            int n;
            int sps;
            int endlabel, starturl, endurl, starttitle, endtitle, endall;
            string url, title;
            endlabel = subj.Position;

            var c = peek_char(subj);

            if (c == '(' &&
                    ((sps = Scanner.scan_spacechars(subj.Buffer, subj.Position + 1, subj.Length)) > -1) &&
                    ((n = Scanner.scan_link_url(subj.Buffer, subj.Position + 1 + sps, subj.Length)) > -1))
            {
                // try to parse an explicit link:
                starturl = subj.Position + 1 + sps; // after (
                endurl = starturl + n;
                starttitle = endurl + Scanner.scan_spacechars(subj.Buffer, endurl, subj.Length);
                // ensure there are spaces btw url and title
                endtitle = (starttitle == endurl) ? starttitle :
                           starttitle + Scanner.scan_link_title(subj.Buffer, starttitle, subj.Length);
                endall = endtitle + Scanner.scan_spacechars(subj.Buffer, endtitle, subj.Length);
                if (endall < subj.Length && subj.Buffer[endall] == ')')
                {
                    subj.Position = endall + 1;
                    url = subj.Buffer.Substring(starturl, endurl - starturl);
                    url = CleanUrl(url);
                    title = subj.Buffer.Substring(starttitle, endtitle - starttitle);
                    title = CleanTitle(title);

                    return new Reference() { Title = title, Url = url };
                }
            }
            else if (c == '[' || c == ' ' || c == '\n')
            {
                var label = ParseReferenceLabel(subj);
                if (label != null)
                {
                    if (label.Value.Length == 0)
                        return Reference.SelfReference;

                    var details = LookupReference(subj.ReferenceMap, label.Value, settings);
                    if (details != null)
                        return details;

                    // rollback the subject but return InvalidReference so that the caller knows not to
                    // parse 'foo' from [foo][bar].
                    subj.Position = endlabel;
                    return Reference.InvalidReference;
                }
            }

            // rollback the subject position because didn't match anything.
            subj.Position = endlabel;
            return null;
        }
Пример #48
0
            /// <summary>
            /// Writes the inline list to the given writer as HTML code.
            /// </summary>
            private static void InlinesToHtml(DocumentationCommentTextWriter writer, Inline inline, CommonMarkSettings settings, ISymbol documentedSymbol, Stack <InlineStackEntry> stack)
            {
                var    uriResolver     = settings.UriResolver;
                bool   withinLink      = false;
                bool   stackWithinLink = false;
                bool   visitChildren;
                string stackLiteral = null;

                while (inline != null)
                {
                    visitChildren = false;

                    switch (inline.Tag)
                    {
                    case InlineTag.String:
                        EscapeHtml(inline.LiteralContent, writer);
                        break;

                    case InlineTag.LineBreak:
                        writer.WriteLineConstant("<br />");
                        break;

                    case InlineTag.SoftBreak:
                        if (settings.RenderSoftLineBreaksAsLineBreaks)
                        {
                            writer.WriteLineConstant("<br />");
                        }
                        else
                        {
                            writer.WriteLine();
                        }

                        break;

                    case InlineTag.Code:
                        if (documentedSymbol.HasAnyParameter(inline.LiteralContent, StringComparer.Ordinal))
                        {
                            writer.WriteConstant("<paramref name=\"");
                            EscapeHtml(inline.LiteralContent, writer);
                            writer.WriteConstant("\"/>");
                        }
                        else if (documentedSymbol.HasAnyTypeParameter(inline.LiteralContent, StringComparer.Ordinal))
                        {
                            writer.WriteConstant("<typeparamref name=\"");
                            EscapeHtml(inline.LiteralContent, writer);
                            writer.WriteConstant("\"/>");
                        }
                        else
                        {
                            writer.WriteConstant("<c>");
                            EscapeHtml(inline.LiteralContent, writer);
                            writer.WriteConstant("</c>");
                        }

                        break;

                    case InlineTag.RawHtml:
                        writer.Write(inline.LiteralContent);
                        break;

                    case InlineTag.Link:
                        if (withinLink)
                        {
                            writer.Write('[');
                            stackLiteral    = "]";
                            stackWithinLink = withinLink;
                            visitChildren   = true;
                        }
                        else
                        {
                            writer.WriteConstant("<see href=\"");
                            if (uriResolver != null)
                            {
                                EscapeUrl(uriResolver(inline.TargetUrl), writer);
                            }
                            else
                            {
                                EscapeUrl(inline.TargetUrl, writer);
                            }

                            writer.Write('\"');
                            if (inline.LiteralContent.Length > 0)
                            {
                                writer.WriteConstant(" title=\"");
                                EscapeHtml(inline.LiteralContent, writer);
                                writer.Write('\"');
                            }

                            writer.Write('>');

                            visitChildren   = true;
                            stackWithinLink = true;
                            stackLiteral    = "</see>";
                        }

                        break;

                    case InlineTag.Image:
                        writer.WriteConstant("<img src=\"");
                        if (uriResolver != null)
                        {
                            EscapeUrl(uriResolver(inline.TargetUrl), writer);
                        }
                        else
                        {
                            EscapeUrl(inline.TargetUrl, writer);
                        }

                        writer.WriteConstant("\" alt=\"");
                        InlinesToPlainText(writer, inline.FirstChild, stack);
                        writer.Write('\"');
                        if (inline.LiteralContent.Length > 0)
                        {
                            writer.WriteConstant(" title=\"");
                            EscapeHtml(inline.LiteralContent, writer);
                            writer.Write('\"');
                        }

                        writer.WriteConstant(" />");
                        break;

                    case InlineTag.Strong:
                        writer.WriteConstant("<strong>");
                        stackLiteral    = "</strong>";
                        stackWithinLink = withinLink;
                        visitChildren   = true;
                        break;

                    case InlineTag.Emphasis:
                        writer.WriteConstant("<em>");
                        stackLiteral    = "</em>";
                        visitChildren   = true;
                        stackWithinLink = withinLink;
                        break;

                    case InlineTag.Strikethrough:
                        writer.WriteConstant("<del>");
                        stackLiteral    = "</del>";
                        visitChildren   = true;
                        stackWithinLink = withinLink;
                        break;

                    default:
                        throw new CommonMarkException("Inline type " + inline.Tag + " is not supported.", inline);
                    }

                    if (visitChildren)
                    {
                        stack.Push(new InlineStackEntry(stackLiteral, inline.NextSibling, withinLink));

                        withinLink = stackWithinLink;
                        inline     = inline.FirstChild;
                    }
                    else if (inline.NextSibling != null)
                    {
                        inline = inline.NextSibling;
                    }
                    else
                    {
                        inline = null;
                    }

                    while (inline == null && stack.Count > 0)
                    {
                        var entry = stack.Pop();
                        writer.WriteConstant(entry.Literal);
                        inline     = entry.Target;
                        withinLink = entry.IsWithinLink;
                    }
                }
            }
Пример #49
0
        /// <summary>
        /// Walk through the block, its children and siblings, parsing string content into inline content where appropriate.
        /// </summary>
        /// <param name="block">The document level block from which to start the processing.</param>
        /// <param name="refmap">The reference mapping used when parsing links.</param>
        /// <param name="settings">The settings that influence how the inline parsing is performed.</param>
        public static void ProcessInlines(Block block, Dictionary<string, Reference> refmap, CommonMarkSettings settings)
        {
            Stack<Inline> inlineStack = null;
            var stack = new Stack<Block>();
            var parsers = settings.InlineParsers;
            var specialCharacters = settings.InlineParserSpecialCharacters;
            var subj = new Subject(refmap);

            StringContent sc;
            int delta;

            while (block != null)
            {
                var tag = block.Tag;
                if (tag == BlockTag.Paragraph || tag == BlockTag.AtxHeader || tag == BlockTag.SETextHeader)
                {
                    sc = block.StringContent;
                    if (sc != null)
                    {
                        sc.FillSubject(subj);
                        delta = subj.Position;

                        block.InlineContent = InlineMethods.parse_inlines(subj, refmap, parsers, specialCharacters);
                        block.StringContent = null;

                        if (sc.PositionTracker != null)
                        {
                            sc.PositionTracker.AddBlockOffset(-delta);
                            AdjustInlineSourcePosition(block.InlineContent, sc.PositionTracker, ref inlineStack);
                        }
                    }
                }

                if (block.FirstChild != null)
                {
                    if (block.NextSibling != null)
                        stack.Push(block.NextSibling);

                    block = block.FirstChild;
                }
                else if (block.NextSibling != null)
                {
                    block = block.NextSibling;
                }
                else if (stack.Count > 0)
                {
                    block = stack.Pop();
                }
                else
                {
                    block = null;
                }
            }
        }
Пример #50
0
        private static void BlocksToHtmlInner(HtmlTextWriter writer, Block block, CommonMarkSettings settings)
        {
            var stack = new Stack<BlockStackEntry>();
            var inlineStack = new Stack<InlineStackEntry>();
            bool visitChildren;
            string stackLiteral = null;
            bool stackTight = false;
            bool tight = false;
            bool trackPositions = settings.TrackSourcePosition;
            int x;

            while (block != null)
            {
                visitChildren = false;

                switch (block.Tag)
                {
                    case BlockTag.Document:
                        stackLiteral = null;
                        stackTight = false;
                        visitChildren = true;
                        break;

                    case BlockTag.Paragraph:
                        if (tight)
                        {
                            InlinesToHtml(writer, block.InlineContent, settings, inlineStack);
                        }
                        else
                        {
                            writer.EnsureLine();
                            writer.WriteConstant("<p");
                            if (trackPositions) PrintPosition(writer, block);
                            writer.Write('>');
                            InlinesToHtml(writer, block.InlineContent, settings, inlineStack);
                            writer.WriteLineConstant("</p>");
                        }
                        break;

                    case BlockTag.BlockQuote:
                        writer.EnsureLine();
                        writer.WriteConstant("<blockquote");
                        if (trackPositions) PrintPosition(writer, block);
                        writer.WriteLine('>');

                        stackLiteral = "</blockquote>";
                        stackTight = false;
                        visitChildren = true;
                        break;

                    case BlockTag.ListItem:
                        writer.EnsureLine();
                        writer.WriteConstant("<li");
                        if (trackPositions) PrintPosition(writer, block);
                        writer.Write('>');

                        stackLiteral = "</li>";
                        stackTight = tight;
                        visitChildren = true;
                        break;

                    case BlockTag.List:
                        // make sure a list starts at the beginning of the line:
                        writer.EnsureLine();
                        var data = block.ListData;
                        writer.WriteConstant(data.ListType == ListType.Bullet ? "<ul" : "<ol");
                        if (data.Start != 1)
                        {
                            writer.WriteConstant(" start=\"");
                            writer.WriteConstant(data.Start.ToString(CultureInfo.InvariantCulture));
                            writer.Write('\"');
                        }
                        if (trackPositions) PrintPosition(writer, block);
                        writer.WriteLine('>');

                        stackLiteral = data.ListType == ListType.Bullet ? "</ul>" : "</ol>";
                        stackTight = data.IsTight;
                        visitChildren = true;
                        break;

                    case BlockTag.AtxHeader:
                    case BlockTag.SETextHeader:
                        writer.EnsureLine();

                        x = block.HeaderLevel;

                        if (trackPositions)
                        {
                            writer.WriteConstant("<h" + x.ToString(CultureInfo.InvariantCulture));
                            PrintPosition(writer, block);
                            writer.Write('>');
                            InlinesToHtml(writer, block.InlineContent, settings, inlineStack);
                            writer.WriteLineConstant(x > 0 && x < 7 ? HeaderCloserTags[x - 1] : "</h" + x.ToString(CultureInfo.InvariantCulture) + ">");
                        }
                        else
                        {
                            writer.WriteConstant(x > 0 && x < 7 ? HeaderOpenerTags[x - 1] : "<h" + x.ToString(CultureInfo.InvariantCulture) + ">");
                            InlinesToHtml(writer, block.InlineContent, settings, inlineStack);
                            writer.WriteLineConstant(x > 0 && x < 7 ? HeaderCloserTags[x - 1] : "</h" + x.ToString(CultureInfo.InvariantCulture) + ">");
                        }

                        break;

                    case BlockTag.IndentedCode:
                    case BlockTag.FencedCode:
                        writer.EnsureLine();
                        writer.WriteConstant("<pre><code");
                        if (trackPositions) PrintPosition(writer, block);

                        var info = block.FencedCodeData == null ? null : block.FencedCodeData.Info;
                        if (info != null && info.Length > 0)
                        {
                            x = info.IndexOf(' ');
                            if (x == -1)
                                x = info.Length;

                            writer.WriteConstant(" class=\"language-");
                            EscapeHtml(new StringPart(info, 0, x), writer);
                            writer.Write('\"');
                        }
                        writer.Write('>');
                        EscapeHtml(block.StringContent, writer);
                        writer.WriteLineConstant("</code></pre>");
                        break;

                    case BlockTag.HtmlBlock:
                        // cannot output source position for HTML blocks
                        block.StringContent.WriteTo(writer);

                        break;

                    case BlockTag.HorizontalRuler:
                        if (trackPositions)
                        {
                            writer.WriteConstant("<hr");
                            PrintPosition(writer, block);
                            writer.WriteLine();
                        }
                        else
                        {
                            writer.WriteLineConstant("<hr />");
                        }

                        break;

                    case BlockTag.ReferenceDefinition:
                        break;

                    default:
                        throw new CommonMarkException("Block type " + block.Tag + " is not supported.", block);
                }

                if (visitChildren)
                {
                    stack.Push(new BlockStackEntry(stackLiteral, block.NextSibling, tight));

                    tight = stackTight;
                    block = block.FirstChild;
                }
                else if (block.NextSibling != null)
                {
                    block = block.NextSibling;
                }
                else
                {
                    block = null;
                }

                while (block == null && stack.Count > 0)
                {
                    var entry = stack.Pop();

                    writer.WriteLineConstant(entry.Literal);
                    tight = entry.IsTight;
                    block = entry.Target;
                }
            }
        }
 public TableFormatter(TextWriter target, CommonMarkSettings settings) : base(target, settings)
 {
 }
Пример #52
0
        /// <summary>
        /// Write the block data to the given writer.
        /// </summary>
        public static void PrintBlocks(TextWriter writer, Block block, CommonMarkSettings settings)
        {
            int indent         = 0;
            var stack          = new Stack <BlockStackEntry>();
            var inlineStack    = new Stack <InlineStackEntry>();
            var buffer         = new StringBuilder();
            var trackPositions = settings.TrackSourcePosition;

            while (block != null)
            {
                writer.Write(new string(' ', indent));

                switch (block.Tag)
                {
                case BlockTag.Document:
                    writer.Write("document");
                    PrintPosition(trackPositions, writer, block);
                    break;

                case BlockTag.BlockQuote:
                    writer.Write("block_quote");
                    PrintPosition(trackPositions, writer, block);
                    break;

                case BlockTag.ListItem:
                    writer.Write("list_item");
                    PrintPosition(trackPositions, writer, block);
                    break;

                case BlockTag.List:
                    writer.Write("list");
                    PrintPosition(trackPositions, writer, block);

                    var data = block.ListData;
                    if (data.ListType == ListType.Ordered)
                    {
                        writer.Write(" (type=ordered tight={0} start={1} delim={2})",
                                     data.IsTight,
                                     data.Start,
                                     data.Delimiter);
                    }
                    else
                    {
                        writer.Write("(type=bullet tight={0} bullet_char={1})",
                                     data.IsTight,
                                     data.BulletChar);
                    }
                    break;

                case BlockTag.AtxHeader:
                    writer.Write("atx_header");
                    PrintPosition(trackPositions, writer, block);
                    writer.Write(" (level={0})", block.HeaderLevel);
                    break;

                case BlockTag.SETextHeader:
                    writer.Write("setext_header");
                    PrintPosition(trackPositions, writer, block);
                    writer.Write(" (level={0})", block.HeaderLevel);
                    break;

                case BlockTag.Paragraph:
                    writer.Write("paragraph");
                    PrintPosition(trackPositions, writer, block);
                    break;

                case BlockTag.HorizontalRuler:
                    writer.Write("hrule");
                    PrintPosition(trackPositions, writer, block);
                    break;

                case BlockTag.IndentedCode:
                    writer.Write("indented_code {0}", format_str(block.StringContent.ToString(buffer), buffer));
                    PrintPosition(trackPositions, writer, block);
                    writer.Write(' ');
                    writer.Write(format_str(block.StringContent.ToString(buffer), buffer));
                    break;

                case BlockTag.FencedCode:
                    writer.Write("fenced_code");
                    PrintPosition(trackPositions, writer, block);
                    writer.Write(" length={0} info={1} {2}",
                                 block.FencedCodeData.FenceLength,
                                 format_str(block.FencedCodeData.Info, buffer),
                                 format_str(block.StringContent.ToString(buffer), buffer));
                    break;

                case BlockTag.HtmlBlock:
                    writer.Write("html_block");
                    PrintPosition(trackPositions, writer, block);
                    writer.Write(' ');
                    writer.Write(format_str(block.StringContent.ToString(buffer), buffer));
                    break;

                case BlockTag.ReferenceDefinition:
                    writer.Write("reference_def");
                    PrintPosition(trackPositions, writer, block);
                    break;

                default:
                    throw new CommonMarkException("Block type " + block.Tag + " is not supported.", block);
                }

                writer.WriteLine();

                if (block.InlineContent != null)
                {
                    PrintInlines(writer, block.InlineContent, indent + 2, inlineStack, buffer, trackPositions);
                }

                if (block.FirstChild != null)
                {
                    if (block.NextSibling != null)
                    {
                        stack.Push(new BlockStackEntry(indent, block.NextSibling));
                    }

                    indent += 2;
                    block   = block.FirstChild;
                }
                else if (block.NextSibling != null)
                {
                    block = block.NextSibling;
                }
                else if (stack.Count > 0)
                {
                    var entry = stack.Pop();
                    indent = entry.Indent;
                    block  = entry.Target;
                }
                else
                {
                    block = null;
                }
            }
        }
Пример #53
0
        // Process one line at a time, modifying a block.
        // Returns 0 if successful.  curptr is changed to point to
        // the currently open block.
        public static void IncorporateLine(LineInfo line, ref Block curptr, CommonMarkSettings settings)
        {
            var parameters = settings.BlockParserParameters;

            var ln = line.Line;

            Block last_matched_container;
            
            // offset is the char position in the line
            var offset = 0;

            // column is the virtual position in the line that takes TAB expansion into account
            var column = 0;

            // the char position of the first non-space char
            int first_nonspace;

            // the virtual position of the first non-space chart, that includes TAB expansion
            int first_nonspace_column;

            int matched;
            int i;
            ListData data;
            bool all_matched = true;
            Block cur = curptr;
            var blank = false;
            char curChar;
            int indent;

            // container starts at the document root.
            var container = cur.Top;

            // for each containing block, try to parse the associated line start.
            // bail out on failure:  container will point to the last matching block.

            while (container.LastChild != null && container.LastChild.IsOpen)
            {
                container = container.LastChild;

                FindFirstNonspace(ln, offset, column, out first_nonspace, out first_nonspace_column, out curChar);

                indent = first_nonspace_column - column;
                blank = curChar == '\n';

                switch (container.Tag)
                {
                    case BlockTag.BlockQuote:
                        {
                            if (indent <= 3 && curChar == '>')
                            {
                                AdvanceOffset(ln, indent + 1, true, ref offset, ref column);
                                if (ln[offset] == ' ')
                                    offset++;
                            }
                            else
                            {
                                all_matched = false;
                            }

                            break;
                        }

                    case BlockTag.ListItem:
                        {
                            if (indent >= container.ListData.MarkerOffset + container.ListData.Padding)
                            {
                                AdvanceOffset(ln, container.ListData.MarkerOffset + container.ListData.Padding, true, ref offset, ref column);
                            }
                            else if (blank && container.FirstChild != null)
                            {
                                // if container->first_child is NULL, then the opening line
                                // of the list item was blank after the list marker; in this
                                // case, we are done with the list item.
                                AdvanceOffset(ln, first_nonspace - offset, false, ref offset, ref column);
                            }
                            else
                            {
                                all_matched = false;
                            }

                            break;
                        }

                    case BlockTag.IndentedCode:
                        {
                            if (indent >= CODE_INDENT)
                                AdvanceOffset(ln, CODE_INDENT, true, ref offset, ref column);
                            else if (blank)
                                AdvanceOffset(ln, first_nonspace - offset, false, ref offset, ref column);
                            else
                                all_matched = false;

                            break;
                        }

                    case BlockTag.AtxHeader:
                    case BlockTag.SETextHeader:
                        {
                            // a header can never contain more than one line
                            all_matched = false;
                            if (blank)
                                container.IsLastLineBlank = true;

                            break;
                        }

                    case BlockTag.FencedCode:
                    case BlockTag.CustomContainer:
                        {
                            // -1 means we've seen closer 
                            if (container.FencedCodeData.FenceLength == -1)
                            {
                                all_matched = false;
                                if (blank)
                                    container.IsLastLineBlank = true;
                            }
                            else
                            {
                                // skip optional spaces of fence offset
                                i = container.FencedCodeData.FenceOffset;
                                while (i > 0 && ln[offset] == ' ')
                                {
                                    offset++;
                                    column++;
                                    i--;
                                }
                            }

                            break;
                        }

                    case BlockTag.HtmlBlock:
                        {
                            // all other block types can accept blanks
                            if (blank && container.HtmlBlockType >= HtmlBlockType.InterruptingBlock)
                            {
                                container.IsLastLineBlank = true;
                                all_matched = false;
                            }

                            break;
                        }

                    case BlockTag.Paragraph:
                        {
                            if (blank)
                            {
                                container.IsLastLineBlank = true;
                                all_matched = false;
                            }

                            break;
                        }
                }

                if (!all_matched)
                {
                    container = container.Parent;  // back up to last matching block
                    break;
                }
            }

            last_matched_container = container;

            // check to see if we've hit 2nd blank line, break out of list:
            if (blank && container.IsLastLineBlank)
                BreakOutOfLists(ref container, line, settings);

            var maybeLazy = cur.Tag == BlockTag.Paragraph;

            // unless last matched container is code block, try new container starts:
            while (container.Tag != BlockTag.FencedCode &&
                   container.Tag != BlockTag.IndentedCode &&
                   container.Tag != BlockTag.CustomContainer &&
                   container.Tag != BlockTag.HtmlBlock)
            {

                FindFirstNonspace(ln, offset, column, out first_nonspace, out first_nonspace_column, out curChar);

                indent = first_nonspace_column - column;
                blank = curChar == '\n';

                var indented = indent >= CODE_INDENT;

                if (!indented && curChar == '>')
                {

                    AdvanceOffset(ln, first_nonspace + 1 - offset, false, ref offset, ref column);
                    // optional following character
                    if (ln[offset] == ' ')
                    {
                        offset++;
                        column++;
                    }

                    container = CreateChildBlock(container, line, BlockTag.BlockQuote, first_nonspace, settings);

                }
                else if (!indented && curChar == '#' && 0 != (matched = Scanner.scan_atx_header_start(ln, first_nonspace, ln.Length, out i)))
                {

                    AdvanceOffset(ln, first_nonspace + matched - offset, false, ref offset, ref column);
                    container = CreateChildBlock(container, line, BlockTag.AtxHeader, first_nonspace, settings);
                    container.HeaderLevel = i;

                }
                else if (!indented && parameters.IsFenceDelimiter(curChar) && 0 != (matched = Scanner.scan_open_code_fence(ln, first_nonspace, ln.Length, parameters)))
                {

                    var blockTag = curChar == ':'
                        ? BlockTag.CustomContainer
                        : BlockTag.FencedCode;
                    container = CreateChildBlock(container, line, blockTag, first_nonspace, settings);
                    container.FencedCodeData = new FencedCodeData();
                    container.FencedCodeData.FenceChar = curChar;
                    container.FencedCodeData.FenceLength = matched;
                    container.FencedCodeData.FenceOffset = first_nonspace - offset;

                    AdvanceOffset(ln, first_nonspace + matched - offset, false, ref offset, ref column);

                }
                else if (!indented && curChar == '<' && 
                    (0 != (matched = (int)Scanner.scan_html_block_start(ln, first_nonspace, ln.Length))
                    || (container.Tag != BlockTag.Paragraph && 0 != (matched = (int)Scanner.scan_html_block_start_7(ln, first_nonspace, ln.Length)))
                    ))
                {

                    container = CreateChildBlock(container, line, BlockTag.HtmlBlock, first_nonspace, settings);
                    container.HtmlBlockType = (HtmlBlockType)matched;
                    // note, we don't adjust offset because the tag is part of the text

                }
                else if (!indented && container.Tag == BlockTag.Paragraph && parameters.IsSETextHeaderDelimiter(curChar)
                        && 0 != (matched = Scanner.scan_setext_header_line(ln, first_nonspace, ln.Length, parameters))
                        && ContainsSingleLine(container.StringContent))
                {

                    container.Tag = BlockTag.SETextHeader;
                    container.HeaderLevel = matched;
                    AdvanceOffset(ln, ln.Length - 1 - offset, false, ref offset, ref column);

                }
                else if (!indented 
                    && !(container.Tag == BlockTag.Paragraph && !all_matched) 
                    && 0 != (Scanner.scan_hrule(ln, first_nonspace, ln.Length)))
                {

                    // it's only now that we know the line is not part of a setext header:
                    container = CreateChildBlock(container, line, BlockTag.HorizontalRuler, first_nonspace, settings);
                    Finalize(container, line, settings);
                    container = container.Parent;
                    AdvanceOffset(ln, ln.Length - 1 - offset, false, ref offset, ref column);

                }
                else if ((!indented || container.Tag == BlockTag.List) 
                    && 0 != (matched = ParseListMarker(ln, first_nonspace, out data)))
                {

                    // compute padding:
                    AdvanceOffset(ln, first_nonspace + matched - offset, false, ref offset, ref column);
                    i = 0;
                    while (i <= 5 && ln[offset + i] == ' ')
                        i++;

                    // i = number of spaces after marker, up to 5
                    if (i >= 5 || i < 1 || ln[offset] == '\n')
                    {
                        data.Padding = matched + 1;
                        if (i > 0)
                        {
                            column++;
                            offset++;
                        }
                    }
                    else
                    {
                        data.Padding = matched + i;
                        AdvanceOffset(ln, i, true, ref offset, ref column);
                    }

                    // check container; if it's a list, see if this list item
                    // can continue the list; otherwise, create a list container.

                    data.MarkerOffset = indent;

                    if (container.Tag != BlockTag.List || !ListsMatch(container.ListData, data))
                    {
                        container = CreateChildBlock(container, line, BlockTag.List, first_nonspace, settings);
                        container.ListData = data;
                    }

                    // add the list item
                    container = CreateChildBlock(container, line, BlockTag.ListItem, first_nonspace, settings);
                    container.ListData = data;
                }
                else if (indented && !maybeLazy && !blank)
                {
                    AdvanceOffset(ln, CODE_INDENT, true, ref offset, ref column);
                    container = CreateChildBlock(container, line, BlockTag.IndentedCode, offset, settings);
                }
                else
                {
                    break;
                }

                if (AcceptsLines(container.Tag))
                {
                    // if it's a line container, it can't contain other containers
                    break;
                }

                maybeLazy = false;
            }

            // what remains at offset is a text line.  add the text to the
            // appropriate container.

            FindFirstNonspace(ln, offset, column, out first_nonspace, out first_nonspace_column, out curChar);
            indent = first_nonspace_column - column;
            blank = curChar == '\n';

            if (blank && container.LastChild != null)
            {
                container.LastChild.IsLastLineBlank = true;
            }

            // block quote lines are never blank as they start with >
            // and we don't count blanks in fenced code for purposes of tight/loose
            // lists or breaking out of lists.  we also don't set last_line_blank
            // on an empty list item.
            container.IsLastLineBlank = (blank &&
                                          container.Tag != BlockTag.BlockQuote &&
                                          container.Tag != BlockTag.SETextHeader &&
                                          container.Tag != BlockTag.FencedCode &&
                                          container.Tag != BlockTag.CustomContainer &&
                                          !(container.Tag == BlockTag.ListItem &&
                                            container.FirstChild == null &&
                                            container.SourcePosition >= line.LineOffset));

            Block cont = container;
            while (cont.Parent != null)
            {
                cont.Parent.IsLastLineBlank = false;
                cont = cont.Parent;
            }

            if (cur != last_matched_container &&
                container == last_matched_container &&
                !blank &&
                cur.Tag == BlockTag.Paragraph &&
                cur.StringContent.Length > 0)
            {

                AddLine(cur, line, ln, offset);

            }
            else
            { // not a lazy continuation

                // finalize any blocks that were not matched and set cur to container:
                while (cur != last_matched_container)
                {

                    Finalize(cur, line, settings);
                    cur = cur.Parent;

                    if (cur == null)
                        throw new CommonMarkException("Cannot finalize container block. Last matched container tag = " + last_matched_container.Tag);

                }

                if (container.Tag == BlockTag.IndentedCode)
                {

                    AddLine(container, line, ln, offset);

                }
                else if (container.Tag == BlockTag.FencedCode || container.Tag == BlockTag.CustomContainer)
                {

                    if ((indent <= 3
                      && curChar == container.FencedCodeData.FenceChar)
                      && (0 != Scanner.scan_close_code_fence(ln, first_nonspace, container.FencedCodeData.FenceLength, ln.Length, parameters)))
                    {
                        // if closing fence, set fence length to -1. it will be closed when the next line is processed. 
                        container.FencedCodeData.FenceLength = -1;
                    }
                    else
                    {
                        AddLine(container, line, ln, offset);
                    }

                }
                else if (container.Tag == BlockTag.HtmlBlock)
                {

                    AddLine(container, line, ln, offset);

                    if (Scanner.scan_html_block_end(container.HtmlBlockType, ln, first_nonspace, ln.Length))
                    {
                        Finalize(container, line, settings);
                        container = container.Parent;
                    }

                }
                else if (blank)
                {

                    // ??? do nothing

                }
                else if (container.Tag == BlockTag.AtxHeader)
                {

                    int p = ln.Length - 1;

                    // trim trailing spaces
                    while (p >= 0 && (ln[p] == ' ' || ln[p] == '\n'))
                        p--;

                    // if string ends in #s, remove these:
                    while (p >= 0 && ln[p] == '#')
                        p--;

                    // there must be a space before the last hashtag
                    if (p < 0 || ln[p] != ' ')
                        p = ln.Length - 1;

                    AddLine(container, line, ln, first_nonspace, p - first_nonspace + 1);
                    Finalize(container, line, settings);
                    container = container.Parent;

                }
                else if (AcceptsLines(container.Tag))
                {

                    AddLine(container, line, ln, first_nonspace);

                }
                else if (container.Tag != BlockTag.HorizontalRuler && container.Tag != BlockTag.SETextHeader)
                {

                    // create paragraph container for line
                    container = CreateChildBlock(container, line, BlockTag.Paragraph, first_nonspace, settings);
                    AddLine(container, line, ln, first_nonspace);

                }
                else
                {

                    Utilities.Warning("Line {0} with container type {1} did not match any condition:\n\"{2}\"", line.LineNumber, container.Tag, ln);

                }

                curptr = container;
            }
        }
Пример #54
0
 public static void BlocksToHtml(TextWriter writer, Block block, CommonMarkSettings settings)
 {
     var wrapper = new HtmlTextWriter(writer);
     BlocksToHtmlInner(wrapper, block, settings);
 }
Пример #55
0
        private void BlocksToXamlInner(FlowDocument parent, Block block, CommonMarkSettings settings)
        {
            _checkBoxNumber = 0;
            var  stack          = new Stack <BlockStackEntry>();
            var  inlineStack    = new Stack <InlineStackEntry>();
            bool stackTight     = false;
            bool tight          = false;
            bool trackPositions = settings.TrackSourcePosition;
            int  x;

            IAddChild blockParent = parent;

            while (block != null)
            {
                var       visitChildren = false;
                IAddChild lastParent    = null;

                switch (block.Tag)
                {
                case BlockTag.Document:
                    stackTight    = false;
                    visitChildren = true;
                    lastParent    = parent;
                    break;

                case BlockTag.Paragraph:
                    if (tight)
                    {
                        InlinesToXaml(blockParent, block.InlineContent, settings, inlineStack);
                    }
                    else
                    {
                        Paragraph paragraph = new Paragraph();
                        if (trackPositions)
                        {
                            PrintPosition(paragraph, block);
                        }
                        InlinesToXaml(paragraph, block.InlineContent, settings, inlineStack);
                        blockParent.AddChild(paragraph);
                    }
                    break;

                case BlockTag.BlockQuote:
                    Section blockquoteParagraph = new Section();
                    if (trackPositions)
                    {
                        PrintPosition(blockquoteParagraph, block);
                    }

                    if (QuoteStyle != null)
                    {
                        blockquoteParagraph.Style = QuoteStyle;
                    }

                    blockParent.AddChild(blockquoteParagraph);
                    lastParent  = blockParent;
                    blockParent = blockquoteParagraph;

                    stackTight    = true;
                    visitChildren = true;
                    break;

                case BlockTag.ListItem:

                    stackTight = tight;

                    if (block.ListData != null && block.ListData.ListType == ListType.TaskList)
                    {
                        BlockUIContainer ctnr = (BlockUIContainer)blockParent;
                        StackPanel       sp   = (StackPanel)ctnr.Child;

                        visitChildren = false;
                        TextBlock spcb = new TextBlock();
                        spcb.Style = TodoTextStyle;
                        Inline checkBoxInline = block.FirstChild?.InlineContent;
                        if (checkBoxInline != null)
                        {
                            InlinesToXaml(spcb, checkBoxInline, settings, inlineStack);
                        }

                        CheckBox bt = new CheckBox
                        {
                            IsChecked = block.TaskListItemIsChecked,
                            Content   = spcb,
                            Tag       = _checkBoxNumber
                        };
                        bt.CommandParameter = bt;
                        bt.Command          = CheckBoxCheckedCommand;
                        bt.Style            = TodoCheckBoxStyle;

                        sp.Children.Add(bt);

                        //TODO: Add child stack panel and add block.FirstChild.NextSibling

                        _checkBoxNumber++;
                    }
                    else
                    {
                        ListItem listItem = new ListItem();
                        if (ListItemStyle != null)
                        {
                            listItem.Style = ListItemStyle;
                        }

                        if (trackPositions)
                        {
                            PrintPosition(listItem, block);
                        }

                        blockParent.AddChild(listItem);

                        lastParent    = blockParent;
                        blockParent   = listItem;
                        visitChildren = true;
                    }

                    break;

                case BlockTag.List:
                    var       data = block.ListData;
                    IAddChild list;
                    if (data.ListType == ListType.TaskList)
                    {
                        StackPanel sp = new StackPanel();
                        list = new BlockUIContainer(sp);
                    }
                    else
                    {
                        List theList = new List();
                        list = theList;
                        theList.MarkerStyle = data.ListType == ListType.Bullet ? TextMarkerStyle.Disc : TextMarkerStyle.Decimal;

                        if (ListStyle != null)
                        {
                            theList.Style = ListStyle;
                        }
                    }

                    if (trackPositions)
                    {
                        PrintPosition((FrameworkContentElement)list, block);
                    }

                    // TODO: Check if first child starts with [ ] then it is a todo-list item
                    // TODO: Set list.StartIndex if > 1

                    blockParent.AddChild(list);
                    lastParent  = blockParent;
                    blockParent = list;

                    stackTight    = data.IsTight;
                    visitChildren = true;
                    break;

                case BlockTag.AtxHeading:
                case BlockTag.SetextHeading:
                    Paragraph headerParagraph = new Paragraph();
                    if (trackPositions)
                    {
                        PrintPosition(headerParagraph, block);
                    }

                    InlinesToXaml(headerParagraph, block.InlineContent, settings, inlineStack);

                    x = block.Heading.Level;

                    switch (x)
                    {
                    case 1:
                        headerParagraph.Style = Heading1Style;
                        break;

                    case 2:
                        headerParagraph.Style = Heading2Style;
                        break;

                    case 3:
                        headerParagraph.Style = Heading3Style;
                        break;

                    case 4:
                        headerParagraph.Style = Heading4Style;
                        break;

                    default:
                        headerParagraph.Style = Heading1Style;
                        break;
                    }

                    blockParent.AddChild(headerParagraph);

                    break;

                case BlockTag.IndentedCode:
                case BlockTag.FencedCode:
                    Paragraph codeblockParagraph = new Paragraph();

                    if (trackPositions)
                    {
                        PrintPosition(codeblockParagraph, block);
                    }

                    if (CodeBlockStyle != null)
                    {
                        codeblockParagraph.Style = CodeBlockStyle;
                    }

                    var info = block.FencedCodeData == null ? null : block.FencedCodeData.Info;
                    if (info != null && info.Length > 0)
                    {
                        //x = info.IndexOf(' ');
                        //if (x == -1)
                        //	x = info.Length;

                        //parent.WriteConstant(" class=\"language-");
                        //EscapeHtml(new StringPart(info, 0, x), parent);
                        //parent.Write('\"');
                    }

                    EscapeHtml(block.StringContent, codeblockParagraph);

                    blockParent.AddChild(codeblockParagraph);
                    break;

                case BlockTag.HtmlBlock:
                    // cannot output source position for HTML blocks
                    // block.StringContent.WriteTo(parent);

                    //TODO: Unable to convert html to

                    break;

                case BlockTag.ThematicBreak:
                    var line = new Line()
                    {
                        X2 = 1, StrokeThickness = 1.0
                    };
                    var container = new BlockUIContainer(line);
                    if (trackPositions)
                    {
                        PrintPosition(container, block);
                    }

                    if (LineStyle != null)
                    {
                        line.Style = LineStyle;
                    }

                    blockParent.AddChild(container);
                    break;

                case BlockTag.Table:
                    WriteTable(block, blockParent, settings, inlineStack);
                    break;

                case BlockTag.ReferenceDefinition:
                    break;

                default:
                    throw new CommonMarkException("Block type " + block.Tag + " is not supported.", block);
                }

                if (visitChildren)
                {
                    stack.Push(new BlockStackEntry(lastParent, block.NextSibling, tight));

                    tight = stackTight;
                    block = block.FirstChild;
                }
                else if (block.NextSibling != null)
                {
                    block = block.NextSibling;
                }
                else
                {
                    block = null;
                }

                while (block == null && stack.Count > 0)
                {
                    var entry = stack.Pop();

                    blockParent = entry.Parent;
                    tight       = entry.IsTight;
                    block       = entry.Target;
                }
            }
        }
Пример #56
0
        /// <summary>
        /// Collapses internal whitespace to single space, removes leading/trailing whitespace, folds case.
        /// </summary>
        private static string NormalizeReference(StringPart s, CommonMarkSettings settings)
        {
            if (s.Length == 0)
                return string.Empty;

            var result = NormalizeWhitespace(s.Source, s.StartIndex, s.Length);
            if (0 == (settings.AdditionalFeatures & CommonMarkAdditionalFeatures.RespectReferenceCase))
                result = result.ToUpperInvariant();
            return result;
        }
Пример #57
0
        /// <summary>
        /// Checks if the reference dictionary contains a reference with the given label and returns it,
        /// otherwise returns <c>null</c>.
        /// Returns <see cref="Reference.InvalidReference"/> if the reference label is not valid.
        /// </summary>
        private static Reference LookupReference(Dictionary<string, Reference> refmap, StringPart lab, CommonMarkSettings settings)
        {
            if (refmap == null)
                return null;

            if (lab.Length > Reference.MaximumReferenceLabelLength)
                return Reference.InvalidReference;

            string label = NormalizeReference(lab, settings);

            Reference r;
            if (refmap.TryGetValue(label, out r))
                return r;

            return null;
        }
 public MarkdownHighlightingColorizer()
 {
     _commonMarkSettings = CommonMarkSettings.Default.Clone();
     _commonMarkSettings.TrackSourcePosition = true;
 }
Пример #59
0
        // Parse reference.  Assumes string begins with '[' character.
        // Modify refmap if a reference is encountered.
        // Return 0 if no reference found, otherwise position of subject
        // after reference is parsed.
        public static int ParseReference(Subject subj, CommonMarkSettings settings)
        {
            string title;
            var startPos = subj.Position;

            // parse label:
            var lab = ParseReferenceLabel(subj);
            if (lab == null || lab.Value.Length > Reference.MaximumReferenceLabelLength)
                goto INVALID;

            if (!Scanner.HasNonWhitespace(lab.Value))
                goto INVALID;

            // colon:
            if (peek_char(subj) == ':')
                subj.Position++;
            else
                goto INVALID;

            // parse link url:
            spnl(subj);
            var matchlen = Scanner.scan_link_url(subj.Buffer, subj.Position, subj.Length);
            if (matchlen == 0)
                goto INVALID;

            var url = subj.Buffer.Substring(subj.Position, matchlen);
            url = CleanUrl(url);
            subj.Position += matchlen;

            // parse optional link_title
            var beforetitle = subj.Position;
            spnl(subj);

            matchlen = Scanner.scan_link_title(subj.Buffer, subj.Position, subj.Length);
            if (matchlen > 0)
            {
                title = subj.Buffer.Substring(subj.Position, matchlen);
                title = CleanTitle(title);
                subj.Position += matchlen;
            }
            else
            {
                subj.Position = beforetitle;
                title = string.Empty;
            }

            char c;
            // parse final spaces and newline:
            while ((c = peek_char(subj)) == ' ') subj.Position++;

            if (c == '\n')
            {
                subj.Position++;
            }
            else if (c != '\0')
            {
                if (matchlen > 0)
                { // try rewinding before title
                    subj.Position = beforetitle;
                    while ((c = peek_char(subj)) == ' ') subj.Position++;
                    if (c == '\n')
                        subj.Position++;
                    else if (c != '\0')
                       goto INVALID;
                }
                else
                {
                    goto INVALID;
                }
            }

            // insert reference into refmap
            AddReference(subj.ReferenceMap, lab.Value, url, title, settings);

            return subj.Position;

        INVALID:
            subj.Position = startPos;
            return 0;
        }