private void EndElement(ParserContext context, IDocumentElement element) { var linkElement = element as ILinkElement; switch (element.ElementType) { case ElementTypes.Container: context.IsPreFormatted = false; context.Template.AddElementClose(); context.Template.AddLineBreak(); break; case ElementTypes.InlineText: context.Template.AddElementClose(); break; case ElementTypes.Heading: case ElementTypes.Paragraph: context.Template.AddElementClose(); context.Template.AddLineBreak(); break; case ElementTypes.Link: if (linkElement != null && linkElement.LinkType == LinkTypes.Reference) { context.Template.AddElementClose(); } break; } }
public bool Write(IDocumentElement element) { switch (element.ElementType) { case ElementTypes.Document: return(WriteDocument(element)); case ElementTypes.Break: return(WriteBreak(element)); case ElementTypes.Container: return(WriteContainer(element)); case ElementTypes.Heading: return(WriteHeading(element)); case ElementTypes.InlineText: return(WriteInlineText(element)); case ElementTypes.Link: return(WriteLink(element)); case ElementTypes.Paragraph: return(WriteParagraph(element)); } var textElement = element as ITextElement; if (textElement != null && !string.IsNullOrEmpty(textElement.Text)) { _textWriter.Write(textElement.Text); } return(true); }
private void CollapseLineBreaks(IDocumentElement element) { var nextIsLineBreak = false; for (var i = element.Children.Count - 2; i >= 0; i--) { var current = element.Children[i] as IBreakElement; if (current != null && current.BreakType == BreakTypes.LineBreak) { if (nextIsLineBreak) { element.Children.RemoveAt(i + 1); } else { var next = element.Children[i + 1] as IBreakElement; if (next != null && next.BreakType == BreakTypes.LineBreak) { element.Children.RemoveAt(i + 1); } nextIsLineBreak = true; } } else { i--; nextIsLineBreak = false; } } }
public void CleanDocument(IDocumentElement element, DocumentCleaning actions) { if (element == null || element.Children == null || element.Children.Count == 0) { return; } if ((actions & (DocumentCleaning.RemoveBlankLines | DocumentCleaning.MakeParagraphs)) != 0) { RemoveEmptyTextElements(element); CollapseLineBreaks(element); } if (actions.HasFlag(DocumentCleaning.MakeParagraphs)) { MakeParagraphs(element); } foreach (var child in element.Children) { CleanDocument(child, actions); } if (actions.HasFlag(DocumentCleaning.RemoveBlankLines)) { RemoveEmptyContainers(element); } }
private bool WriteHeading(IDocumentElement element) { var nestedElement = element as INestedElement; var headingLevel = 1; if (nestedElement != null) { headingLevel = nestedElement.Level; } _characterStream.State = MarkdownStates.Heading; _textWriter.EnsureBlankLine(); _textWriter.Write(new string('#', headingLevel)); _textWriter.Write(' '); if (element.Children != null) { foreach (var child in element.Children) { Write(child); } } _textWriter.EnsureNewLine(); return(true); }
public void AddToParagraph(IDocumentElement elementToAdd) { Contract.Requires(elementToAdd != null); Contract.Ensures(currentParagraph != null); CreateParagraphIfNoneIsAlreadyOpen(); currentParagraph.AddChild(elementToAdd); }
private string RenderMarkdown(IDocumentElement document) { var output = new StringBuilder(); using (var textWriter = new StringWriter(output)) { _documentTransformer.FormatDocument("text/x-markdown", textWriter, document); } return(output.ToString()); }
private void MakeParagraphs(IDocumentElement element) { for (var i = element.Children.Count - 1; i >= 0; i--) { var lineBreak = element.Children[i] as IBreakElement; { if (lineBreak != null && lineBreak.BreakType == BreakTypes.LineBreak) { var first = i; while (first > 0) { var textElement = element.Children[first - 1]; var linkElement = textElement as ILinkElement; if (textElement.ElementType == ElementTypes.RawText || textElement.ElementType == ElementTypes.InlineText || (textElement.ElementType == ElementTypes.Link && linkElement != null && (linkElement.LinkType == LinkTypes.Reference || linkElement.LinkType == LinkTypes.Image)) ) { first--; } else { break; } } if (first == i) { continue; } var paragraph = new ParagraphElement { Parent = element, Children = new List <IDocumentElement>() }; element.Children[i] = paragraph; for (var j = first; j < i; j++) { var childToMove = element.Children[first]; paragraph.Children.Add(childToMove); childToMove.Parent = paragraph; element.Children.RemoveAt(first); } i = first; } } } }
private void FixupChildren(IDocumentElement element) { if (element.Children != null) { foreach (var child in element.Children) { child.Parent = element; FixupChildren(child); } } }
private bool WriteDocument(IDocumentElement element) { if (element.Children != null) { foreach (var child in element.Children) { Write(child); } } return(true); }
private bool WriteLink(IDocumentElement element) { var linkElement = element as ILinkElement; if (linkElement == null) { return(false); } _textWriter.Write(linkElement.LinkAddress); return(true); }
private T FindPriorElement <T>(IDocumentElement start, Func <T, bool> predicate) where T : Element { while (start != null) { var t = start as T; if (t != null && predicate(t)) { return(t); } start = start.Parent; } return(null); }
private void Write(ParserContext context, IDocumentElement element) { BeginElement(context, element); if (element.Children != null) { foreach (var child in element.Children) { Write(context, child); } } EndElement(context, element); }
public void Write(IDocumentElement element) { WriteElementBegin(element); if (element.Children != null) { foreach (var child in element.Children) { Write(child); } } WriteElementEnd(element); }
public void CleanAttributes(IDocumentElement element, Func <IDocumentElement, string, string, bool> attributeFilter) { if (element == null || attributeFilter == null) { return; } if (element.Children != null) { foreach (var child in element.Children) { CleanAttributes(child, attributeFilter); } } }
public TElement AssertElement <TElement> (int index, Action <TElement> assertAction = null) where TElement : IDocumentElement { Contract.Requires(index >= 0); Contract.Ensures(Contract.Result <TElement>() != null); IDocumentElement element = doc.Children[index]; Assert.IsInstanceOf <TElement> (element); if (assertAction != null) { assertAction((TElement)element); } return((TElement)element); }
private bool WriteHeading(IDocumentElement element) { _textWriter.EnsureBlankLine(); if (element.Children != null) { foreach (var child in element.Children) { Write(child); } } _textWriter.EnsureNewLine(); return(true); }
private void RemoveEmptyContainers(IDocumentElement element) { for (var i = element.Children.Count - 1; i >= 0; i--) { var child = element.Children[i]; if (child != null && (child.ElementType == ElementTypes.Container || child.ElementType == ElementTypes.Paragraph) && (child.Children == null || child.Children.Count == 0)) { var container = child as IContainerElement; if (container != null && container.ContainerType == ContainerTypes.TableDataCell) { continue; // Empty cells in tables are valid, deleting them moves all the other columns to the left } element.Children.RemoveAt(i); } } }
private bool WriteInlineText(IDocumentElement element) { var textElement = element as ITextElement; if (textElement != null) { _textWriter.Write(textElement.Text); } if (element.Children != null) { foreach (var child in element.Children) { Write(child); } } return(true); }
private bool WriteParagraph(IDocumentElement element) { var textElement = element as ITextElement; if (textElement != null && !string.IsNullOrEmpty(textElement.Text)) { _textWriter.Write(textElement.Text); } if (element.Children != null) { foreach (var child in element.Children) { Write(child); } } return(true); }
public void AddTextToParagraph(string text, bool isFirstElementOfContinuedLine) { Contract.Requires(text != null); CreateParagraphIfNoneIsAlreadyOpen(); int childrenCount = currentParagraph.ChildrenCount; if (childrenCount > 0) { IDocumentElement lastChild = currentParagraph.Children[childrenCount - 1]; TextElement textChild = lastChild as TextElement; if (textChild != null) { // ReSharper disable once PossibleInvalidOperationException if (textChild.Style == currentParagraphTextStyle.Value) { textChild.AppendText(text); } else { AddTextElementToParagraph( currentParagraph, text, currentParagraphTextStyle.Value, isFirstElementOfContinuedLine); } } else if (lastChild is InternalLinkElement || lastChild is ExternalLinkElement) { // ReSharper disable once PossibleInvalidOperationException AddTextElementToParagraph( currentParagraph, text, currentParagraphTextStyle.Value, isFirstElementOfContinuedLine); } else { throw new InvalidOperationException("BUG: is this possible?"); } } else { // ReSharper disable once PossibleInvalidOperationException AddToParagraph(CreateTextElement(text, currentParagraphTextStyle.Value)); } }
public void CleanElements(IDocumentElement element, Func <IDocumentElement, bool> elementFilter) { if (element == null || elementFilter == null || element.Children == null) { return; } for (var i = element.Children.Count - 1; i >= 0; i--) { var child = element.Children[i]; if (elementFilter(child)) { CleanElements(child, elementFilter); } else { element.Children.RemoveAt(i); } } }
private void RemoveEmptyTextElements(IDocumentElement element) { for (var i = element.Children.Count - 1; i >= 0; i--) { var child = element.Children[i]; if (child != null && (child.ElementType == ElementTypes.RawText || child.ElementType == ElementTypes.InlineText) && (child.Children == null || child.Children.Count == 0)) { var text = child as ITextElement; if (text != null && !string.IsNullOrEmpty(text.Text)) { continue; } element.Children.RemoveAt(i); } } }
public ParsingFixture AssertText( IDocumentElementContainer container, int index, string expectedText, TextElement.TextStyle?expectedStyle = null) { Contract.Requires(container != null); Contract.Requires(expectedText != null); Contract.Requires(index >= 0); IDocumentElement element = container.Children[index]; Assert.IsInstanceOf <TextElement> (element); TextElement tel = (TextElement)element; Assert.AreEqual(expectedText, tel.Text); if (expectedStyle.HasValue) { Assert.AreEqual(expectedStyle.Value, tel.Style); } return(this); }
private bool WriteInlineText(IDocumentElement element) { var textElement = element as ITextElement; var styleElement = element as IStyleElement; Action close = null; if (styleElement != null && styleElement.Styles != null) { if (styleElement.Styles.ContainsKey("font-weight") && styleElement.Styles["font-weight"] == "bold") { _textWriter.Write("**"); close = () => _textWriter.Write("**"); } else if (styleElement.Styles.ContainsKey("font-style") && styleElement.Styles["font-style"] == "italic") { _textWriter.Write("_"); close = () => _textWriter.Write("_"); } } if (textElement != null) { _textWriter.Write(textElement.Text); } if (element.Children != null) { foreach (var child in element.Children) { Write(child); } } if (close != null) { close(); } return(true); }
public void FormatDocument(string mimeType, System.IO.TextWriter writer, IDocumentElement rootElement, bool fragment) { if (string.Equals(mimeType, "text/html", StringComparison.OrdinalIgnoreCase)) { FormatHtml(writer, rootElement, fragment); } else if (string.Equals(mimeType, "text/x-markdown", StringComparison.OrdinalIgnoreCase)) { FormatMarkdown(writer, rootElement, fragment); } else if (string.Equals(mimeType, "text/plain", StringComparison.OrdinalIgnoreCase)) { FormatPlainText(writer, rootElement, fragment); } else { throw new NotImplementedException(); } }
private static void BeginParagraphElement(ParserContext context, IDocumentElement element, string[] attributeParams) { if (element.Parent.ElementType == ElementTypes.Container) { var parentContainer = element.Parent as IContainerElement; if (parentContainer != null && (parentContainer.ContainerType == ContainerTypes.BareList || parentContainer.ContainerType == ContainerTypes.BulletList || parentContainer.ContainerType == ContainerTypes.NumberedList)) { context.Template.AddElementOpen("li", attributeParams); } else { context.Template.AddElementOpen("p", attributeParams); } } else { context.Template.AddElementOpen("p", attributeParams); } }
public void AdjustHeadings(IDocumentElement element, int minimumHeadingLevel) { Action <IDocumentElement, List <INestedElement> > addHeadings = null; addHeadings = (e, hl) => { var h = e as INestedElement; if (e.ElementType == ElementTypes.Heading && h != null) { hl.Add(h); } if (e.Children != null) { foreach (var child in e.Children) { addHeadings(child, hl); } } }; var headings = new List <INestedElement>(); addHeadings(element, headings); if (headings.Count > 0) { var lowestHeading = headings.Min(h => h.Level); if (lowestHeading > 1) { foreach (var heading in headings) { heading.Level = heading.Level - lowestHeading + minimumHeadingLevel; } } } }
private bool WriteBreak(IDocumentElement element) { var breakElement = element as IBreakElement; var breakType = BreakTypes.LineBreak; if (breakElement != null) { breakType = breakElement.BreakType; } _textWriter.EnsureBlankLine(); switch (breakType) { case BreakTypes.HorizontalRule: _characterStream.State = MarkdownStates.HorizontalRule; _textWriter.Write("---"); _textWriter.EnsureBlankLine(); break; } return(true); }
private bool WriteContainer(IDocumentElement element) { var containerElement = element as IContainerElement; var configurableElement = element as IConfigurableElement; if (containerElement == null) { return(false); } Action close = null; switch (containerElement.ContainerType) { case ContainerTypes.BlockQuote: _textWriter.EnsureBlankLine(); _characterStream.State = MarkdownStates.BlockQuote; close = () => _textWriter.EnsureBlankLine(); break; case ContainerTypes.BulletList: _listLevel++; if (_listLevel == 0) { _textWriter.EnsureBlankLine(); } _characterStream.State = MarkdownStates.UnorderedList; close = () => { if (_listLevel == 0) { _textWriter.EnsureBlankLine(); } _listLevel--; }; break; case ContainerTypes.NumberedList: _listLevel++; while (_listItemNumber.Count <= _listLevel) { _listItemNumber.Add(0); } _listItemNumber[_listLevel] = 1; if (_listLevel == 0) { _textWriter.EnsureBlankLine(); } _characterStream.State = MarkdownStates.NumberedList; close = () => { if (_listLevel == 0) { _textWriter.EnsureBlankLine(); } _listLevel--; }; break; case ContainerTypes.PreFormatted: _textWriter.EnsureBlankLine(); _characterStream.State = MarkdownStates.SourceCode; _textWriter.Write("```"); _textWriter.WriteLineBreak(); close = () => { _textWriter.EnsureNewLine(); _textWriter.Write("```"); _textWriter.EnsureBlankLine(); }; break; case ContainerTypes.Table: containerElement.ChildLayout = new TableLayout(); _textWriter.EnsureBlankLine(); _characterStream.State = MarkdownStates.TableHeadings; close = () => _textWriter.EnsureBlankLine(); break; case ContainerTypes.TableHeader: close = () => { var table = FindPriorElement <ContainerElement>(element, c => c.ContainerType == ContainerTypes.Table); if (table == null) { return; } var tableLayout = table.ChildLayout as TableLayout; if (tableLayout == null) { return; } var tableBody = table.Children .Where(e => e.ElementType == ElementTypes.Container) .Cast <IContainerElement>() .FirstOrDefault(c => c.ContainerType == ContainerTypes.TableBody); if (tableBody != null) { var tableBodyChildren = ((IDocumentElement)tableBody).Children; if (tableBodyChildren != null) { foreach (var tableRow in tableBodyChildren .Where(c => c.ElementType == ElementTypes.Container && c.Children != null) .Cast <IContainerElement>() .Where(c => c.ContainerType == ContainerTypes.TableDataRow) .Cast <IDocumentElement>()) { var columnIndex = 0; foreach (var dataCell in tableRow.Children .Where(c => c.ElementType == ElementTypes.Container && c.Children != null) .Cast <IContainerElement>() .Where(c => c.ContainerType == ContainerTypes.TableDataCell) .Cast <IConfigurableElement>()) { string alignment = null; if (dataCell != null && dataCell.Attributes != null && dataCell.Attributes.ContainsKey("align")) { alignment = dataCell.Attributes["align"]; } tableLayout.SetColumn(columnIndex++, alignment, null); } } } } _textWriter.EnsureNewLine(); _textWriter.Write('|'); foreach (var tableColumn in tableLayout.Columns) { var padding = new string('-', tableColumn.Width); switch (tableColumn.Alignment) { case "left": _textWriter.Write(':'); _textWriter.Write(padding); _textWriter.Write(' '); break; case "right": _textWriter.Write(' '); _textWriter.Write(padding); _textWriter.Write(':'); break; case "center": _textWriter.Write(':'); _textWriter.Write(padding); _textWriter.Write(':'); break; default: _textWriter.Write(' '); _textWriter.Write(padding); _textWriter.Write(' '); break; } _textWriter.Write('|'); } }; break; case ContainerTypes.TableHeaderRow: case ContainerTypes.TableDataRow: case ContainerTypes.TableFooterRow: _textWriter.EnsureNewLine(); _characterStream.State = MarkdownStates.TableRow; _textWriter.Write("|"); _tableColumnIndex = 0; break; case ContainerTypes.TableDataCell: { var align = string.Empty; if (configurableElement != null && configurableElement.Attributes != null) { if (configurableElement.Attributes.ContainsKey("align")) { align = configurableElement.Attributes["align"]; } } var table = FindPriorElement <ContainerElement>(element, c => c.ContainerType == ContainerTypes.Table); var tableLayout = (TableLayout)table.ChildLayout; tableLayout.SetColumn(_tableColumnIndex, align, null); _tableColumnIndex++; _characterStream.State = MarkdownStates.TableRow; _textWriter.Write(" "); close = () => _textWriter.Write(" |"); break; } } if (element.Children != null) { foreach (var child in element.Children) { Write(child); } } if (close != null) { close(); } return(true); }