static void FormatInlines(Settings settings, CMInline cmInline, InlineCollection wdInlines) { for (; cmInline != null; cmInline = cmInline.NextSibling) { switch (cmInline.Tag) { case InlineTag.Emphasis: var wdItalic = new Italic(); FormatInlines(settings, cmInline.FirstChild, wdItalic.Inlines); wdInlines.Add(wdItalic); break; case InlineTag.Strong: var wdBold = new Bold(); FormatInlines(settings, cmInline.FirstChild, wdBold.Inlines); wdInlines.Add(wdBold); break; case InlineTag.Link: var wdLink = new Hyperlink(); var url = cmInline.TargetUrl; if (settings.UrlResolver != null) { url = settings.UrlResolver(url); } wdLink.NavigateUri = new Uri(url); FormatInlines(settings, cmInline.FirstChild, wdLink.Inlines); wdInlines.Add(wdLink); break; case InlineTag.Placeholder: var placeholder = cmInline.TargetUrl; if (settings.PlaceholderResolver != null) { placeholder = settings.PlaceholderResolver(placeholder); } wdInlines.Add(new Run(placeholder)); break; case InlineTag.SoftBreak: wdInlines.Add(new Run(" ")); break; case InlineTag.LineBreak: wdInlines.Add(new LineBreak()); break; case InlineTag.String: wdInlines.Add(new Run(cmInline.LiteralContent)); break; default: throw new NotImplementedException($"InlineTag.{cmInline.Tag}"); } } }
private static void PrintPosition(bool enabled, TextWriter writer, Inline inline) { if (enabled) { writer.Write(" ["); writer.Write(inline.SourcePosition); writer.Write('-'); writer.Write(inline.SourceLastPosition); writer.Write(']'); } }
public static IEnumerable<Inline> EnumerateInlines(Inline inline) { if (inline == null) yield break; var stack = new Stack<Inline>(); stack.Push(inline); while (stack.Any()) { var next = stack.Pop(); yield return next; if (next.NextSibling != null) stack.Push(next.NextSibling); if (next.FirstChild != null) stack.Push(next.FirstChild); } }
private void HandleImage(Inline inline, IAddChild parent) { NoteFile nf = CurrentNote.Files.FirstOrDefault(n => n.FileName == inline.TargetUrl); Paragraph result = parent as Paragraph; if (result == null) { result = new Paragraph(); parent.AddChild(result); } if (nf != null && File.Exists(nf.FullName)) { if (!string.IsNullOrWhiteSpace(inline.LiteralContent)) { result.ToolTip = inline.LiteralContent; } var imageUri = new Uri(nf.FullName, UriKind.Absolute); var imgTemp = new BitmapImage(); imgTemp.BeginInit(); imgTemp.CacheOption = BitmapCacheOption.OnLoad; imgTemp.CreateOptions = BitmapCreateOptions.IgnoreImageCache; imgTemp.UriSource = imageUri; imgTemp.EndInit(); var image = new Image { Source = imgTemp, Stretch = Stretch.None, StretchDirection = StretchDirection.Both, MaxWidth = imgTemp.Width, MaxHeight = imgTemp.Height }; if (ImageStyle != null) { image.Style = ImageStyle; } result.Inlines.Add(image); } else if (nf != null) { result.Inlines.Add(new Run("Missing file: " + nf.FullName)); } }
internal override async Task WriteConceptualLinkAsync(Inline inline) { if (GetSectionState() != SectionState.SeeAlso) { await base.WriteConceptualLinkAsync(inline); return; } var target = GetConceptualLinkTarget(inline.TargetUrl); if (!target.StartsWith("#")) return; var termId = target.TrimStart('#'); await WriteStartElementAsync("relatedEntry"); await WriteAttributeStringAsync("termId", termId); await WriteEndElementAsync(); //relatedEntry }
private async Task WriteInlineAsync(Inline inline) { switch (inline.Tag) { case InlineTag.String: await WriteStringAsync(inline); break; case InlineTag.Emphasis: await WriteWeakEmphasisAsync(inline); break; case InlineTag.Strong: await WriteStrongEmphasisAsync(inline); break; default: throw new InvalidOperationException("Unexpected inline tag: " + inline.Tag); } }
/// <summary> /// Writes the specified inline element to the output stream. Does not write the child nodes, instead /// the <paramref name="ignoreChildNodes"/> is used to notify the caller whether it should recurse /// into the child nodes. /// </summary> /// <param name="inline">The inline element to be written to the output stream.</param> /// <param name="isOpening">Specifies whether the inline element is being opened (or started).</param> /// <param name="isClosing">Specifies whether the inline element is being closed. If the inline does not /// have child nodes, then both <paramref name="isClosing"/> and <paramref name="isOpening"/> can be /// <see langword="true"/> at the same time.</param> /// <param name="ignoreChildNodes">Instructs the caller whether to skip processing of child nodes or not.</param> protected virtual void WriteInline(Inline inline, bool isOpening, bool isClosing, out bool ignoreChildNodes) { if (RenderPlainTextInlines.Peek()) { switch (inline.Tag) { case InlineTag.String: case InlineTag.Code: case InlineTag.RawHtml: WriteEncodedHtml(inline.LiteralContentValue); break; case InlineTag.LineBreak: case InlineTag.SoftBreak: WriteLine(); break; case InlineTag.Image: if (isOpening) RenderPlainTextInlines.Push(true); if (isClosing) { RenderPlainTextInlines.Pop(); if (!RenderPlainTextInlines.Peek()) goto useFullRendering; } break; case InlineTag.Link: case InlineTag.Strong: case InlineTag.Emphasis: case InlineTag.Strikethrough: case InlineTag.Placeholder: break; default: throw new CommonMarkException("Inline type " + inline.Tag + " is not supported.", inline); } ignoreChildNodes = false; return; } useFullRendering: switch (inline.Tag) { case InlineTag.String: ignoreChildNodes = true; if (Settings.TrackSourcePosition) { Write("<span"); WritePositionAttribute(inline); Write('>'); WriteEncodedHtml(inline.LiteralContentValue); Write("</span>"); } else { WriteEncodedHtml(inline.LiteralContentValue); } break; case InlineTag.LineBreak: ignoreChildNodes = true; WriteLine("<br />"); break; case InlineTag.SoftBreak: ignoreChildNodes = true; if (Settings.RenderSoftLineBreaksAsLineBreaks) WriteLine("<br />"); else WriteLine(); break; case InlineTag.Code: ignoreChildNodes = true; Write("<code"); if (Settings.TrackSourcePosition) WritePositionAttribute(inline); Write('>'); WriteEncodedHtml(inline.LiteralContentValue); Write("</code>"); break; case InlineTag.RawHtml: ignoreChildNodes = true; // cannot output source position for HTML blocks Write(inline.LiteralContentValue); break; case InlineTag.Link: ignoreChildNodes = false; if (isOpening) { Write("<a href=\""); var uriResolver = Settings.UriResolver; if (uriResolver != null) WriteEncodedUrl(uriResolver(inline.TargetUrl)); else WriteEncodedUrl(inline.TargetUrl); Write('\"'); if (inline.LiteralContentValue.Length > 0) { Write(" title=\""); WriteEncodedHtml(inline.LiteralContentValue); Write('\"'); } if (Settings.TrackSourcePosition) WritePositionAttribute(inline); Write('>'); } if (isClosing) { Write("</a>"); } break; case InlineTag.Image: ignoreChildNodes = false; if (isOpening) { Write("<img src=\""); var uriResolver = Settings.UriResolver; if (uriResolver != null) WriteEncodedUrl(uriResolver(inline.TargetUrl)); else WriteEncodedUrl(inline.TargetUrl); Write("\" alt=\""); if (!isClosing) RenderPlainTextInlines.Push(true); } if (isClosing) { // this.RenderPlainTextInlines.Pop() is done by the plain text renderer above. Write('\"'); if (inline.LiteralContentValue.Length > 0) { Write(" title=\""); WriteEncodedHtml(inline.LiteralContentValue); Write('\"'); } if (Settings.TrackSourcePosition) WritePositionAttribute(inline); Write(" />"); } break; case InlineTag.Strong: ignoreChildNodes = false; if (isOpening) { Write("<strong"); if (Settings.TrackSourcePosition) WritePositionAttribute(inline); Write('>'); } if (isClosing) { Write("</strong>"); } break; case InlineTag.Emphasis: ignoreChildNodes = false; if (isOpening) { Write("<em"); if (Settings.TrackSourcePosition) WritePositionAttribute(inline); Write('>'); } if (isClosing) { Write("</em>"); } break; case InlineTag.Strikethrough: ignoreChildNodes = false; if (isOpening) { Write("<del"); if (Settings.TrackSourcePosition) WritePositionAttribute(inline); Write('>'); } if (isClosing) { Write("</del>"); } break; case InlineTag.Placeholder: ignoreChildNodes = false; if (isOpening) { string placeholderSubstitute = null; try { placeholderSubstitute = (_placeholderResolver != null) ? _placeholderResolver(inline.TargetUrl) : null; } catch (Exception ex) { throw new CommonMarkException("An error occurred while resolving a placeholder.", ex); } if (placeholderSubstitute != null) { ignoreChildNodes = true; if (Settings.TrackSourcePosition) WritePositionAttribute(inline); Write(placeholderSubstitute); _endPlaceholders.Push('\0'); } else { ignoreChildNodes = false; Write("["); _endPlaceholders.Push(']'); } } if (isClosing) { var closingChar = _endPlaceholders.Pop(); if (closingChar != '\0') { Write(closingChar); } } break; default: throw new CommonMarkException("Inline type " + inline.Tag + " is not supported.", inline); } }
/// <summary> /// Initializes a new instance of the <see cref="EnumeratorEntry"/> class. /// </summary> /// <param name="opening">Specifies if this instance represents the opening of the inline element.</param> /// <param name="closing">Specifies if this instance represents the closing of the inline element (returned by the /// enumerator after the children have been enumerated). Both <paramref name="closing"/> and <paramref name="opening"/> /// can be specified at the same time if there are no children for the <paramref name="inline"/> element.</param> /// <param name="inline">The inlien element being returned from the enumerator.</param> public EnumeratorEntry(bool opening, bool closing, Inline inline) { this.IsOpening = opening; this.IsClosing = closing; this.Inline = inline; }
internal static Inline CreateLink(Inline label, string url, string title) { return new Inline() { Tag = InlineTag.Link, FirstChild = label, TargetUrl = url, LiteralContent = title }; }
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; } } }
/// <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; } } }
// Parse an autolink or HTML tag. // Assumes the subject has a '<' character at the current position. static Inline handle_pointy_brace(Subject subj) { int matchlen; string contents; // advance past first < subj.Position++; // first try to match a URL autolink matchlen = Scanner.scan_autolink_uri(subj.Buffer, subj.Position, subj.Length); if (matchlen > 0) { contents = subj.Buffer.Substring(subj.Position, matchlen - 1); var resultContents = ParseStringEntities(contents); var result = Inline.CreateLink(resultContents, contents, string.Empty); result.SourcePosition = subj.Position - 1; resultContents.SourcePosition = subj.Position; subj.Position += matchlen; result.SourceLastPosition = subj.Position; resultContents.SourceLastPosition = subj.Position - 1; return result; } // next try to match an email autolink matchlen = Scanner.scan_autolink_email(subj.Buffer, subj.Position, subj.Length); if (matchlen > 0) { contents = subj.Buffer.Substring(subj.Position, matchlen - 1); var resultContents = ParseStringEntities(contents); var result = Inline.CreateLink(resultContents, "mailto:" + contents, string.Empty); result.SourcePosition = subj.Position - 1; resultContents.SourcePosition = subj.Position; subj.Position += matchlen; result.SourceLastPosition = subj.Position; resultContents.SourceLastPosition = subj.Position - 1; return result; } // finally, try to match an html tag matchlen = Scanner.scan_html_tag(subj.Buffer, subj.Position, subj.Length); if (matchlen > 0) { var result = new Inline(InlineTag.RawHtml, subj.Buffer, subj.Position - 1, matchlen + 1); result.SourcePosition = subj.Position - 1; subj.Position += matchlen; result.SourceLastPosition = subj.Position; return result; } else { // if nothing matches, just return the opening <: return new Inline("<", subj.Position - 1, subj.Position); } }
public InlineStackEntry(IAddChild parent, Inline target, bool isWithinLink) { Parent = parent; Target = target; IsWithinLink = isWithinLink; }
/// <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 InlineStackEntry(string literal, Inline target, bool isWithinLink) { Literal = literal; Target = target; IsWithinLink = isWithinLink; }
internal static void PrintPosition(HtmlTextWriter writer, Inline inline) { writer.WriteConstant(" data-sourcepos=\""); writer.WriteConstant(inline.SourcePosition.ToString(CultureInfo.InvariantCulture)); writer.Write('-'); writer.WriteConstant(inline.SourceLastPosition.ToString(CultureInfo.InvariantCulture)); writer.WriteConstant("\""); }
/// <summary> /// Writes the inline list to the given writer as plain text (without any HTML tags). /// </summary> /// <seealso href="https://github.com/jgm/CommonMark/issues/145"/> private static void InlinesToPlainText(HtmlTextWriter writer, Inline inline, Stack<InlineStackEntry> stack) { bool withinLink = false; bool stackWithinLink = false; bool visitChildren; string stackLiteral = null; var origStackCount = stack.Count; while (inline != null) { visitChildren = false; switch (inline.Tag) { case InlineTag.String: case InlineTag.Code: case InlineTag.RawHtml: EscapeHtml(inline.LiteralContentValue, writer); break; case InlineTag.LineBreak: case InlineTag.SoftBreak: writer.WriteLine(); break; case InlineTag.Link: if (withinLink) { writer.Write('['); stackLiteral = "]"; visitChildren = true; stackWithinLink = true; } else { visitChildren = true; stackWithinLink = true; stackLiteral = string.Empty; } break; case InlineTag.Image: visitChildren = true; stackWithinLink = true; stackLiteral = string.Empty; break; case InlineTag.Strong: case InlineTag.Emphasis: case InlineTag.Strikethrough: stackLiteral = string.Empty; stackWithinLink = withinLink; visitChildren = true; 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 > origStackCount) { var entry = stack.Pop(); writer.WriteConstant(entry.Literal); inline = entry.Target; withinLink = entry.IsWithinLink; } } }
private async Task WriteBlockImageAsync(Inline inline) { await WriteStartElementAsync("mediaLink"); await WriteStartElementAsync("image"); await WriteLinkTargetAsync(inline.TargetUrl); await WriteEndElementAsync(); //image if (inline.FirstChild != null) await WriteCaptionAsync(inline); await WriteEndElementAsync(); //mediaLink }
public InlineStackEntry(int indent, Inline target) { this.Indent = indent; this.Target = target; }
private static void PrintInlines(TextWriter writer, Inline inline, int indent, Stack<InlineStackEntry> stack, StringBuilder buffer, bool trackPositions) { while (inline != null) { writer.Write(new string(' ', indent)); switch (inline.Tag) { case InlineTag.String: writer.Write("str"); PrintPosition(trackPositions, writer, inline); writer.Write(' '); writer.Write(format_str(inline.LiteralContent, buffer)); break; case InlineTag.LineBreak: writer.Write("linebreak"); PrintPosition(trackPositions, writer, inline); break; case InlineTag.SoftBreak: writer.Write("softbreak"); PrintPosition(trackPositions, writer, inline); break; case InlineTag.Code: writer.Write("code {0}", format_str(inline.LiteralContent, buffer)); PrintPosition(trackPositions, writer, inline); writer.Write(' '); writer.Write(format_str(inline.LiteralContent, buffer)); break; case InlineTag.RawHtml: writer.Write("html {0}", format_str(inline.LiteralContent, buffer)); writer.Write(' '); writer.Write(format_str(inline.LiteralContent, buffer)); break; case InlineTag.Link: writer.Write("link"); PrintPosition(trackPositions, writer, inline); writer.Write(" url={0} title={1}", format_str(inline.TargetUrl, buffer), format_str(inline.LiteralContent, buffer)); break; case InlineTag.Image: writer.Write("image"); PrintPosition(trackPositions, writer, inline); writer.Write(" url={0} title={1}", format_str(inline.TargetUrl, buffer), format_str(inline.LiteralContent, buffer)); break; case InlineTag.Strong: writer.Write("strong"); PrintPosition(trackPositions, writer, inline); break; case InlineTag.Emphasis: writer.Write("emph"); PrintPosition(trackPositions, writer, inline); break; case InlineTag.Strikethrough: writer.Write("del"); PrintPosition(trackPositions, writer, inline); break; case InlineTag.Subscript: writer.Write("sub"); PrintPosition(trackPositions, writer, inline); break; case InlineTag.Superscript: writer.Write("sup"); PrintPosition(trackPositions, writer, inline); break; case InlineTag.Math: writer.Write("math"); PrintPosition(trackPositions, writer, inline); break; default: writer.Write("unknown: " + inline.Tag.ToString()); PrintPosition(trackPositions, writer, inline); break; } writer.WriteLine(); if (inline.FirstChild != null) { if (inline.NextSibling != null) stack.Push(new InlineStackEntry(indent, inline.NextSibling)); indent += 2; inline = inline.FirstChild; } else if (inline.NextSibling != null) { inline = inline.NextSibling; } else if (stack.Count > 0) { var entry = stack.Pop(); indent = entry.Indent; inline = entry.Target; } else { inline = null; } } }
internal static void PrintPosition(HtmlTextWriter writer, Inline inline) { writer.WriteConstant(" lmo=\""); writer.WriteConstant((inline.SourcePosition).ToString(CultureInfo.InvariantCulture)); writer.WriteConstant("\" lmc=\""); writer.WriteConstant((inline.SourceLastPosition).ToString(CultureInfo.InvariantCulture)); writer.WriteConstant("\""); }
private static Inline HandleTilde(Subject subj) { bool canOpen, canClose; var numdelims = ScanEmphasisDelimeters(subj, '~', out canOpen, out canClose); if (numdelims == 1) return new Inline("~", subj.Position - 1, subj.Position); if (canClose) { // walk the stack and find a matching opener, if there is one var istack = InlineStack.FindMatchingOpener(subj.LastPendingInline, InlineStack.InlineStackPriority.Emphasis, '~', out canClose); if (istack != null) { MatchInlineStack(istack, subj, numdelims, null, null, InlineTag.Strikethrough); // if the closer was not fully used, move back a char or two and try again. if (numdelims > 2) { subj.Position = subj.Position - numdelims + 2; // use recursion only if it will not be very deep. if (numdelims < 10) return HandleTilde(subj); } return null; } } var inlText = new Inline(subj.Buffer, subj.Position - numdelims, numdelims, subj.Position - numdelims, subj.Position); if (canOpen || canClose) { var istack = new InlineStack(); istack.DelimeterCount = numdelims; istack.Delimeter = '~'; istack.StartingInline = inlText; istack.Priority = InlineStack.InlineStackPriority.Emphasis; istack.Flags = (canOpen ? InlineStack.InlineStackFlags.Opener : 0) | (canClose ? InlineStack.InlineStackFlags.Closer : 0); InlineStack.AppendStackEntry(istack, subj); } return inlText; }
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; }
/// <summary> /// Writes the specified inline element to the output stream. Does not write the child nodes, instead /// the <paramref name="ignoreChildNodes"/> is used to notify the caller whether it should recurse /// into the child nodes. /// </summary> /// <param name="inline">The inline element to be written to the output stream.</param> /// <param name="isOpening">Specifies whether the inline element is being opened (or started).</param> /// <param name="isClosing">Specifies whether the inline element is being closed. If the inline does not /// have child nodes, then both <paramref name="isClosing"/> and <paramref name="isOpening"/> can be /// <c>true</c> at the same time.</param> /// <param name="ignoreChildNodes">Instructs the caller whether to skip processing of child nodes or not.</param> protected virtual void WriteInline(Inline inline, bool isOpening, bool isClosing, out bool ignoreChildNodes) { if (RenderPlainTextInlines.Peek()) { switch (inline.Tag) { case InlineTag.String: case InlineTag.Code: case InlineTag.RawHtml: WriteEncodedHtml(inline.LiteralContentValue); break; case InlineTag.LineBreak: case InlineTag.SoftBreak: WriteLine(); break; case InlineTag.Image: if (isOpening) RenderPlainTextInlines.Push(true); if (isClosing) { RenderPlainTextInlines.Pop(); if (!RenderPlainTextInlines.Peek()) goto useFullRendering; } break; case InlineTag.Link: case InlineTag.Strong: case InlineTag.Emphasis: case InlineTag.Strikethrough: case InlineTag.Math: break; default: throw new CommonMarkException("Inline type " + inline.Tag + " is not supported.", inline); } ignoreChildNodes = false; return; } useFullRendering: switch (inline.Tag) { case InlineTag.String: ignoreChildNodes = true; if (Settings.TrackSourcePosition) { Write("<span"); WritePositionAttribute(inline); Write('>'); WriteEncodedHtml(inline.LiteralContentValue); Write("</span>"); } else { WriteEncodedHtml(inline.LiteralContentValue); } break; case InlineTag.LineBreak: ignoreChildNodes = true; WriteLine("<br />"); break; case InlineTag.SoftBreak: ignoreChildNodes = true; if (Settings.RenderSoftLineBreaksAsLineBreaks) WriteLine("<br />"); else WriteLine(); break; case InlineTag.Code: ignoreChildNodes = true; Write("<code"); if (Settings.TrackSourcePosition) WritePositionAttribute(inline); Write('>'); WriteEncodedHtml(inline.LiteralContentValue); Write("</code>"); break; case InlineTag.RawHtml: ignoreChildNodes = true; // cannot output source position for HTML blocks Write(inline.LiteralContentValue); break; case InlineTag.Link: ignoreChildNodes = false; if (isOpening) { Write("<a href=\""); var uriResolver = Settings.UriResolver; if (uriResolver != null) WriteEncodedUrl(uriResolver(inline.TargetUrl)); else WriteEncodedUrl(inline.TargetUrl); Write('\"'); if (inline.LiteralContentValue.Length > 0) { Write(" title=\""); WriteEncodedHtml(inline.LiteralContentValue); Write('\"'); } if (Settings.TrackSourcePosition) WritePositionAttribute(inline); Write('>'); } if (isClosing) { Write("</a>"); } break; case InlineTag.Image: ignoreChildNodes = false; if (isOpening) { Write("<img src=\""); var uriResolver = Settings.UriResolver; if (uriResolver != null) WriteEncodedUrl(uriResolver(inline.TargetUrl)); else WriteEncodedUrl(inline.TargetUrl); Write("\" alt=\""); if (!isClosing) RenderPlainTextInlines.Push(true); } if (isClosing) { // this.RenderPlainTextInlines.Pop() is done by the plain text renderer above. Write('\"'); if (inline.LiteralContentValue.Length > 0) { Write(" title=\""); WriteEncodedHtml(inline.LiteralContentValue); Write('\"'); } if (Settings.TrackSourcePosition) WritePositionAttribute(inline); Write(" />"); } break; case InlineTag.Strong: ignoreChildNodes = false; if (isOpening) { Write("<strong"); if (Settings.TrackSourcePosition) WritePositionAttribute(inline); Write('>'); } if (isClosing) { Write("</strong>"); } break; case InlineTag.Emphasis: ignoreChildNodes = false; if (isOpening) { Write("<em"); if (Settings.TrackSourcePosition) WritePositionAttribute(inline); Write('>'); } if (isClosing) { Write("</em>"); } break; case InlineTag.Strikethrough: ignoreChildNodes = false; if (isOpening) { Write("<del"); if (Settings.TrackSourcePosition) WritePositionAttribute(inline); Write('>'); } if (isClosing) { Write("</del>"); } break; case InlineTag.Subscript: ignoreChildNodes = false; if (isOpening) { Write("<sub"); if (Settings.TrackSourcePosition) WritePositionAttribute(inline); Write('>'); } if (isClosing) { Write("</sub>"); } break; case InlineTag.Superscript: ignoreChildNodes = false; if (isOpening) { Write("<sup"); if (Settings.TrackSourcePosition) WritePositionAttribute(inline); Write('>'); } if (isClosing) { Write("</sup>"); } break; case InlineTag.Math: ignoreChildNodes = false; if (isOpening) { Write("<span class=\"math\""); if (Settings.TrackSourcePosition) WritePositionAttribute(inline); Write('>'); } if (isClosing) { Write("</span>"); } break; default: throw new CommonMarkException("Inline type " + inline.Tag + " is not supported.", inline); } }
private static void AdjustInlineSourcePosition(Inline inline, PositionTracker tracker, ref Stack<Inline> stack) { if (stack == null) stack = new Stack<Inline>(); while (inline != null) { inline.SourcePosition = tracker.CalculateInlineOrigin(inline.SourcePosition, true); inline.SourceLastPosition = tracker.CalculateInlineOrigin(inline.SourceLastPosition, false); if (inline.FirstChild != null) { if (inline.NextSibling != null) stack.Push(inline.NextSibling); inline = inline.FirstChild; } else if (inline.NextSibling != null) { inline = inline.NextSibling; } else if (stack.Count > 0) { inline = stack.Pop(); } else { inline = null; } } }
public InlineStackEntry(Inline target, Inline needsClose) { this.Target = target; this.NeedsClose = needsClose; }
internal static void PrintPosition(FrameworkContentElement writer, Inline inline) { writer.Tag = "DataSourcePos:" + inline.SourcePosition.ToString(CultureInfo.InvariantCulture) + " - " + (inline.SourcePosition + inline.SourceLength).ToString(CultureInfo.InvariantCulture); }
/// <summary> /// Initializes a new instance of the <see cref="Inline"/> class. /// </summary> /// <param name="tag">The type of inline element. Should be one of the types that contain child elements, for example, <see cref="InlineTag.Emphasis"/>.</param> /// <param name="content">The first descendant element of the inline that is being created.</param> public Inline(InlineTag tag, Inline content) { this.Tag = tag; this.FirstChild = content; }
/// <summary> /// Writes the inline list to the given parent as plain text (without any HTML tags). /// </summary> /// <seealso href="https://github.com/jgm/CommonMark/issues/145"/> private void InlinesToPlainText(IAddChild parent, Inline inline, Stack <InlineStackEntry> stack) { bool withinLink = false; bool stackWithinLink = false; string stackLiteral = null; var origStackCount = stack.Count; while (inline != null) { var visitChildren = false; switch (inline.Tag) { case InlineTag.String: case InlineTag.RawHtml: //EscapeHtml(inline.LiteralContent, parent); break; case InlineTag.Code: Span codeSpan = new Span(new Run(inline.LiteralContent)); if (InlineCodeStyle != null) { codeSpan.Style = InlineCodeStyle; } parent.AddChild(codeSpan); break; case InlineTag.LineBreak: case InlineTag.SoftBreak: //parent.WriteLine(); break; case InlineTag.Link: if (withinLink) { //parent.Write('['); stackLiteral = "]"; visitChildren = true; stackWithinLink = true; } else { visitChildren = true; stackWithinLink = true; stackLiteral = string.Empty; } break; case InlineTag.Image: visitChildren = true; stackWithinLink = true; stackLiteral = string.Empty; break; case InlineTag.Strong: case InlineTag.Emphasis: case InlineTag.Strikethrough: stackLiteral = string.Empty; stackWithinLink = withinLink; visitChildren = true; break; case InlineTag.Placeholder: visitChildren = true; break; default: throw new CommonMarkException("Inline type " + inline.Tag + " is not supported.", inline); } if (visitChildren) { stack.Push(new InlineStackEntry(parent, inline.NextSibling, withinLink)); withinLink = stackWithinLink; inline = inline.FirstChild; } else if (inline.NextSibling != null) { inline = inline.NextSibling; } else { inline = null; } while (inline == null && stack.Count > origStackCount) { var entry = stack.Pop(); inline = entry.Target; withinLink = entry.IsWithinLink; } } }
internal static int MatchInlineStack(InlineStack opener, Subject subj, int closingDelimeterCount, InlineStack closer, InlineTag singleCharTag, InlineTag doubleCharTag, InlineParserParameters parameters) { // calculate the actual number of delimeters used from this closer int useDelims; var openerDelims = opener.DelimeterCount; if (closingDelimeterCount < 3 || openerDelims < 3) { useDelims = closingDelimeterCount <= openerDelims ? closingDelimeterCount : openerDelims; if (useDelims == 2 && doubleCharTag == 0) useDelims = 1; if (useDelims == 1 && singleCharTag == 0) return 0; } else if (singleCharTag == 0) useDelims = 2; else if (doubleCharTag == 0) useDelims = 1; else useDelims = closingDelimeterCount % 2 == 0 ? 2 : 1; Inline inl = opener.StartingInline; InlineTag tag = useDelims == 1 ? singleCharTag : doubleCharTag; if (openerDelims == useDelims) { // the opener is completely used up - remove the stack entry and reuse the inline element inl.Tag = tag; inl.LiteralContent = null; inl.FirstChild = inl.NextSibling; inl.NextSibling = null; InlineStack.RemoveStackEntry(opener, subj, closer?.Previous, parameters); } else { // the opener will only partially be used - stack entry remains (truncated) and a new inline is added. opener.DelimeterCount -= useDelims; inl.LiteralContent = inl.LiteralContent.Substring(0, opener.DelimeterCount); inl.SourceLastPosition -= useDelims; inl.NextSibling = new Inline(tag, inl.NextSibling); inl = inl.NextSibling; inl.SourcePosition = opener.StartingInline.SourcePosition + opener.DelimeterCount; } // there are two callers for this method, distinguished by the `closer` argument. // if closer == null it means the method is called during the initial subject parsing and the closer // characters are at the current position in the subject. The main benefit is that there is nothing // parsed that is located after the matched inline element. // if closer != null it means the method is called when the second pass for previously unmatched // stack elements is done. The drawback is that there can be other elements after the closer. if (closer != null) { var clInl = closer.StartingInline; if ((closer.DelimeterCount -= useDelims) > 0) { // a new inline element must be created because the old one has to be the one that // finalizes the children of the emphasis var newCloserInline = new Inline(clInl.LiteralContent.Substring(useDelims)); newCloserInline.SourcePosition = inl.SourceLastPosition = clInl.SourcePosition + useDelims; newCloserInline.SourceLength = closer.DelimeterCount; newCloserInline.NextSibling = clInl.NextSibling; clInl.LiteralContent = null; clInl.NextSibling = null; inl.NextSibling = closer.StartingInline = newCloserInline; } else { inl.SourceLastPosition = clInl.SourceLastPosition; clInl.LiteralContent = null; inl.NextSibling = clInl.NextSibling; clInl.NextSibling = null; } } else if (subj != null) { inl.SourceLastPosition = subj.Position - closingDelimeterCount + useDelims; subj.LastInline = inl; } return useDelims; }
private static System.Windows.Documents.Inline InlineToDocumentInline(CommonMark.Syntax.Inline inline) { if (inline == null) { return(null); } switch (inline.Tag) { case InlineTag.String: return(new Run(inline.LiteralContent)); case InlineTag.LineBreak: return(new LineBreak()); case InlineTag.SoftBreak: return(new Run(" ")); case InlineTag.Code: return(new Run(inline.LiteralContent) { FontFamily = new FontFamily("Courier New") }); case InlineTag.RawHtml: break; case InlineTag.Link: var hyperlink = new Hyperlink(); if (Uri.IsWellFormedUriString(inline.TargetUrl, UriKind.Absolute)) { hyperlink.NavigateUri = new Uri(inline.TargetUrl); hyperlink.RequestNavigate += new RequestNavigateEventHandler(LinkRequestNavigate); } var childInline = InlineToDocumentInline(inline.FirstChild); if (childInline != null) { hyperlink.Inlines.Add(childInline); } return(hyperlink); case InlineTag.Image: Uri uri = null; if (Uri.IsWellFormedUriString(inline.TargetUrl, UriKind.Absolute)) { uri = new Uri(inline.TargetUrl, UriKind.Absolute); } else { uri = new Uri(inline.TargetUrl, UriKind.Relative); } var image = new Image(); image.Source = new BitmapImage(uri); var uiContainer = new BlockUIContainer(image); return(new Floater(uiContainer)); case InlineTag.Strong: return(new Bold(InlineToDocumentInline(inline.FirstChild))); case InlineTag.Emphasis: return(new Italic(InlineToDocumentInline(inline.FirstChild))); case InlineTag.Strikethrough: var span = new Span(InlineToDocumentInline(inline.FirstChild)); span.TextDecorations.Add(new TextDecoration() { Location = TextDecorationLocation.Strikethrough }); return(span); default: throw new CommonMarkException("Inline type " + inline.Tag + " is not supported.", inline); } return(null); }
internal CommonMarkException(string message, Syntax.Inline inline, Exception inner = null) : base(message, inner) { this.InlineElement = inline; }
internal async Task WriteStringAsync(Inline inline) { var content = inline.LiteralContent; if (string.IsNullOrWhiteSpace(content)) await WriteRawAsync(" "); else await WriteStringAsync(content); }
internal static void MatchSquareBracketStack(InlineStack opener, Subject subj, Reference details, InlineParserParameters parameters) { if (details != null) { var inl = opener.StartingInline; var isImage = 0 != (opener.Flags & InlineStack.InlineStackFlags.ImageLink); inl.Tag = isImage ? InlineTag.Image : InlineTag.Link; inl.FirstChild = inl.NextSibling; inl.NextSibling = null; inl.SourceLastPosition = subj.Position; inl.TargetUrl = details.Url; inl.LiteralContent = details.Title; if (!isImage) { // since there cannot be nested links, remove any other link openers before this var temp = opener.Previous; while (temp != null && temp.Priority <= InlineStack.InlineStackPriority.Links) { if (temp.Delimeter == '[' && temp.Flags == opener.Flags) { // mark the previous entries as "inactive" if (temp.DelimeterCount == -1) break; temp.DelimeterCount = -1; } temp = temp.Previous; } } InlineStack.RemoveStackEntry(opener, subj, null, parameters); subj.LastInline = inl; } else { // this looked like a link, but was not. // remove the opener stack entry but leave the inbetween intact InlineStack.RemoveStackEntry(opener, subj, opener, parameters); var inl = new Inline("]", subj.Position - 1, subj.Position); subj.LastInline.LastSibling.NextSibling = inl; subj.LastInline = inl; } }
/// <summary> /// Writes a <c>data-sourcepos="start-end"</c> attribute to the target writer. /// This method should only be called if <see cref="CommonMarkSettings.TrackSourcePosition"/> is set to <see langword="true"/>. /// Note that the attribute is preceded (but not succeeded) by a single space. /// </summary> protected void WritePositionAttribute(Inline inline) { HtmlFormatterSlim.PrintPosition(_target, inline); }
private static void BlockToDocumentBlock(CommonMark.Syntax.Block block, BlockCollection collection) { if (block == null) { return; } switch (block.Tag) { case BlockTag.Document: BlockToDocumentBlock(block.FirstChild, collection); break; case BlockTag.Paragraph: var paragraph = new Paragraph(); CommonMark.Syntax.Inline current = block.InlineContent; while (current != null) { var inline = InlineToDocumentInline(current); if (inline != null) { paragraph.Inlines.Add(inline); } current = current.NextSibling; } collection.Add(paragraph); BlockToDocumentBlock(block.NextSibling, collection); break; case BlockTag.BlockQuote: var quoteBlock = new Section() { Background = Brushes.LightGray, Margin = new Thickness(10) }; collection.Add(quoteBlock); BlockToDocumentBlock(block.FirstChild, quoteBlock.Blocks); BlockToDocumentBlock(block.NextSibling, collection); break; case BlockTag.ListItem: throw new InvalidOperationException(); case BlockTag.List: var listBlock = new List(); collection.Add(listBlock); if (block.FirstChild != null) { if (block.FirstChild.ListData.ListType == ListType.Ordered) { listBlock.MarkerStyle = TextMarkerStyle.Decimal; listBlock.StartIndex = block.FirstChild.ListData.Start; } BlockToDocumentBlock(block.FirstChild, listBlock.ListItems); } BlockToDocumentBlock(block.NextSibling, collection); break; case BlockTag.AtxHeading: case BlockTag.SetextHeading: var heading = GetHeadingItem(block.Heading.Level); heading.Inlines.Add(InlineToDocumentInline(block.InlineContent)); collection.Add(heading); BlockToDocumentBlock(block.NextSibling, collection); break; case BlockTag.IndentedCode: case BlockTag.FencedCode: var codeBlock = new Section() { Background = Brushes.LightGray, Margin = new Thickness(2) }; collection.Add(codeBlock); var code = block.StringContent.TakeFromStart(block.StringContent.Length - 1); codeBlock.Blocks.Add(new Paragraph(new Run(code) { FontFamily = new FontFamily("Courier New") })); BlockToDocumentBlock(block.NextSibling, collection); break; case BlockTag.HtmlBlock: // cannot output source position for HTML blocks //block.StringContent.WriteTo(writer); break; case BlockTag.ThematicBreak: var separator = new Rectangle(); separator.Stroke = new SolidColorBrush(Colors.LightGray); separator.StrokeThickness = 3; separator.Height = 2; separator.Width = double.NaN; var lineBlock = new BlockUIContainer(separator); collection.Add(lineBlock); BlockToDocumentBlock(block.NextSibling, collection); break; case BlockTag.ReferenceDefinition: break; default: throw new CommonMarkException("Block type " + block.Tag + " is not supported.", block); } }
private static Inline HandleOpenerCloser(Subject subj, InlineTag singleCharTag, InlineTag doubleCharTag, InlineParserParameters parameters) { bool canOpen, canClose; var c = subj.Buffer[subj.Position]; var numdelims = ScanEmphasisDelimeters(subj, c, out canOpen, out canClose); if (canClose) { // walk the stack and find a matching opener, if there is one var istack = InlineStack.FindMatchingOpener(subj.LastPendingInline, InlineStack.InlineStackPriority.Emphasis, c, out canClose); if (istack != null) { var useDelims = MatchInlineStack(istack, subj, numdelims, null, singleCharTag, doubleCharTag, parameters); // if the closer was not fully used, move back a char or two and try again. if (useDelims < numdelims) { subj.Position = subj.Position - numdelims + useDelims; // use recursion only if it will not be very deep. if (numdelims < 10) return HandleOpenerCloser(subj, singleCharTag, doubleCharTag, parameters); } return null; } } var inlText = new Inline(subj.Buffer, subj.Position - numdelims, numdelims, subj.Position - numdelims, subj.Position, c); if (canOpen || canClose) { var istack = new InlineStack(); istack.DelimeterCount = numdelims; istack.Delimeter = c; istack.StartingInline = inlText; istack.Priority = InlineStack.InlineStackPriority.Emphasis; istack.Flags = (canOpen ? InlineStack.InlineStackFlags.Opener : 0) | (canClose ? InlineStack.InlineStackFlags.Closer : 0); InlineStack.AppendStackEntry(istack, subj); } return inlText; }
private async Task WriteCaptionAsync(Inline inline) { await WriteStartElementAsync("caption"); await WriteAttributeStringAsync("placement", "after"); await WriteChildInlinesAsync(inline); await WriteEndElementAsync(); //caption }
internal override async Task WriteExternalLinkAsync(Inline inline, string targetUrl) { if (GetSectionState() != SectionState.SeeAlso) await base.WriteExternalLinkAsync(inline, targetUrl); }
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; }