internal PrependBlocksAction(ContainerBlock parent, Block beforeChild) : base(beforeChild.Root) { Param.CheckNotNull(beforeChild, "beforeChild"); BeforeChild = beforeChild; Parent = parent; }
private static ContainerOrTerminalNode ParseBlock(ContainerBlock block, CharacterPositionFinder finder, TextProvider textProvider) { var name = GetName(block, textProvider); var type = GetType(block); var locationSpan = GetLocationSpan(block, finder); var container = new Container { Type = type, Name = name, LocationSpan = locationSpan, HeaderSpan = GetHeaderSpan(block), FooterSpan = GetFooterSpan(block), }; if (block is ListBlock list) { foreach (var listItem in list) { var item = ParseBlock(listItem, finder, textProvider); container.Children.Add(item); } } // TODO: RKN // - Table // - ListBlock // check whether we can use a terminal node instead var child = FinalAdjustAfterParsingComplete(container); return(child); }
public void ParseItemProperties(string source, Item item, ContainerBlock blocks) { foreach (var block in blocks) { ParseItemProperties(source, item, block); } }
/// <summary> /// Writes the children of the specified <see cref="ContainerBlock"/>. /// </summary> /// <param name="containerBlock">The container block.</param> public void WriteChildren(ContainerBlock containerBlock) { if (containerBlock == null) { return; } ThrowHelper.CheckDepthLimit(childrenDepth++); bool saveIsFirstInContainer = IsFirstInContainer; bool saveIsLastInContainer = IsLastInContainer; var children = containerBlock; for (int i = 0; i < children.Count; i++) { IsFirstInContainer = i == 0; IsLastInContainer = i + 1 == children.Count; Write(children[i]); } IsFirstInContainer = saveIsFirstInContainer; IsLastInContainer = saveIsLastInContainer; childrenDepth--; }
public static int GetHeadingLevel(this Block block) { ContainerBlock parent = block.Parent; if (parent != null) { int index = parent.IndexOf(block); for (int i = index; i > -1; i--) { if (parent[i] is HeadingBlock headingBlock) { return(headingBlock.Level); } } } if (block is ContainerBlock containerBlock) { int level = 7; foreach (var child in containerBlock) { if (child is HeadingBlock headingBlock) { if (headingBlock.Level < level) { level = headingBlock.Level; } } } return(level == 7 ? 0 : level); } return(0); }
public void MoveChildren_ThrowsBlockExceptionIfAChildIsNotOfTheExpectedType() { // Arrange const int dummyLineIndex = 6; const int dummyColumn = 2; var dummyChildBlock1 = new DummyChildBlock(null); Block dummyChildBlock2 = _mockRepository.Create <Block>(null).Object; var dummyChildBlock3 = new DummyChildBlock(null); var dummyProxyFencedContainerBlock = new ProxyFencedContainerBlock(0, 0, null, null) { dummyChildBlock1, dummyChildBlock2, dummyChildBlock3 }; ContainerBlock dummyTarget = _mockRepository.Create <ContainerBlock>(null).Object; dummyTarget.Column = dummyColumn; dummyTarget.Line = dummyLineIndex; ExposedCollectionBlockFactory testSubject = CreateExposedCollectionBlockFactory(); // Act and assert BlockException result = Assert.Throws <BlockException>(() => testSubject.ExposedMoveChildren(dummyProxyFencedContainerBlock, dummyTarget)); Assert.Equal(string.Format(Strings.BlockException_BlockException_InvalidBlock, dummyTarget.GetType().Name, dummyLineIndex + 1, dummyColumn, string.Format(Strings.BlockException_Shared_BlockMustOnlyContainASpecificTypeOfBlock, nameof(ContainerBlock), nameof(DummyChildBlock), dummyChildBlock2.GetType().Name)), result.Message); }
private void OnHeadingBlockParsed(BlockProcessor processor, Block block) { if (!(block is HeadingBlock headingBlock) || block is BlogMetadataBlock) { return; } if (headingBlock.Level < 2) { return; // Ignore h1 since there's no point including it. } var document = processor.Document; var toc = document.Where(b => b is TableOfContentsBlock).FirstOrDefault() as TableOfContentsBlock; if (toc == null) { return; } ContainerBlock parent = toc; for (int i = 0; i < headingBlock.Level - 2; i++) // 2 is the minimum level we support, hence -2 { if (!(parent.LastChild is ContainerBlock childContainer)) { childContainer = new ListItemBlock(block.Parser); parent.Add(childContainer); } parent = (ContainerBlock)parent.LastChild; } var headingCopy = new HeadingBlock(block.Parser) { Column = headingBlock.Column, HeaderChar = headingBlock.HeaderChar, Inline = headingBlock.Inline, IsBreakable = headingBlock.IsBreakable, IsOpen = headingBlock.IsOpen, Level = headingBlock.Level, Line = headingBlock.Line, ProcessInlines = headingBlock.ProcessInlines, RemoveAfterProcessInlines = headingBlock.RemoveAfterProcessInlines, Span = headingBlock.Span }; headingCopy.Lines = new StringLineGroup(headingBlock.Lines.Lines.Length); headingCopy.SetAttributes(headingBlock.GetAttributes()); foreach (var line in headingBlock.Lines.Lines) { if (line.Slice.Text == null) { continue; } var textCopy = new StringSlice(line.Slice.Text, line.Slice.Start, line.Slice.End); var reffableLine = new StringLine(ref textCopy); headingCopy.Lines.Add(ref reffableLine); } parent.Add(headingCopy); }
private static string GetTextFromBlockContainer(ContainerBlock container) { StringBuilder builder = new StringBuilder(); GetTextFromBlockContainer(container, builder); return(builder.ToString()); }
/// <summary> /// Replaces a <see cref="ProxyTableBlock"/> with a <see cref="ParagraphBlock"/>. /// </summary> /// <param name="blockProcessor">The <see cref="BlockProcessor"/> processing the <see cref="ProxyTableBlock"/> to undo.</param> /// <param name="proxyTableBlock">The <see cref="ProxyTableBlock"/> to undo.</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="blockProcessor"/> is <c>null</c>.</exception> /// <exception cref="ArgumentNullException">Thrown if <paramref name="proxyTableBlock"/> is <c>null</c>.</exception> protected virtual void Undo(BlockProcessor blockProcessor, ProxyTableBlock proxyTableBlock) { if (blockProcessor == null) { throw new ArgumentNullException(nameof(blockProcessor)); } if (proxyTableBlock == null) { throw new ArgumentNullException(nameof(proxyTableBlock)); } // Discard proxyTableBlock ContainerBlock parent = proxyTableBlock.Parent; blockProcessor.Discard(proxyTableBlock); // Replace with paragraph block ParagraphBlockParser parser = blockProcessor.Parsers.FindExact <ParagraphBlockParser>(); var paragraphBlock = new ParagraphBlock(parser) { Lines = proxyTableBlock.Lines, }; parent.Add(paragraphBlock); blockProcessor.Open(paragraphBlock); }
public void Undo_ReplacesProxyTableBlockWithAParagraphBlock() { // Arrange const string dummyText = "dummyText"; var dummyProxyTableBlock = new ProxyTableBlock(null); dummyProxyTableBlock.Lines = new StringLineGroup(dummyText); BlockParser dummyBlockParser = _mockRepository.Create <BlockParser>().Object; ContainerBlock dummyParent = _mockRepository.Create <ContainerBlock>(dummyBlockParser).Object; // Must specify block parser since we're calling ProcessLine later dummyParent.Add(dummyProxyTableBlock); // Assigns dummyParent to dummyProxyTableBlock.Parent BlockProcessor dummyBlockProcessor = MarkdigTypesFactory.CreateBlockProcessor(); dummyBlockProcessor.Open(dummyParent); dummyBlockProcessor.Open(dummyProxyTableBlock); ExposedFlexiTableBlockParser testSubject = CreateExposedFlexiTableBlockParser(); // Act testSubject.ExposedUndo(dummyBlockProcessor, dummyProxyTableBlock); // Assert Assert.Single(dummyParent); var resultParagraphBlock = dummyParent[0] as ParagraphBlock; Assert.NotNull(resultParagraphBlock); Assert.Equal(dummyText, resultParagraphBlock.Lines.ToString()); // Verify that ParagraphBlock remains open dummyBlockProcessor.ProcessLine(new StringSlice(dummyText)); Assert.Equal($"{dummyText}\n{dummyText}", resultParagraphBlock.Lines.ToString()); }
// Handles closing of FlexiSectionBlocks. A FlexiSectionBlock is closed when another FlexiSectionBlock in the same tree with the same or // lower level opens. internal virtual void UpdateOpenFlexiSectionBlocks(BlockProcessor processor, FlexiSectionBlock flexiSectionBlock) { // Since sectioning content roots like blockquotes have their own discrete section trees, // we maintain a stack of stacks. Each stack represents the open branch of a tree. Stack <Stack <FlexiSectionBlock> > openFlexiSectionBlocks = GetOrCreateOpenFlexiSectionBlocks(processor.Document); // Discard stacks for closed branches while (openFlexiSectionBlocks.Count > 0) { // When a sectioning content root is closed, all of its children are closed, so the last section in its branch // will be closed. Under no circumstance will the section at the tip of a branch be closed without its ancestors // being closed as well. if (openFlexiSectionBlocks.Peek().Peek().IsOpen) { break; } openFlexiSectionBlocks.Pop(); } // Find parent container block - processor.CurrentContainer may be closed. processor.CurrentContainer is only updated when // BlockProcessor.ProcessNewBlocks calls BlockProcessor.CloseAll, so at this point, processor.CurrentContainer may not be the eventual // parent of our new FlexiSectionBlock. ContainerBlock parentContainerBlock = processor.CurrentContainer; while (!parentContainerBlock.IsOpen) // We will eventually reach the root MarkdownDocument (gauranteed to be open) if all other containers aren't open { parentContainerBlock = parentContainerBlock.Parent; } if (!(parentContainerBlock is FlexiSectionBlock)) // parentContainerBlock is a sectioning content root, for example, a blockquote. Create a new stack for a new tree { var newStack = new Stack <FlexiSectionBlock>(); newStack.Push(flexiSectionBlock); openFlexiSectionBlocks.Push(newStack); } else { Stack <FlexiSectionBlock> currentBranch = openFlexiSectionBlocks.Peek(); // If parentContainerBlock is a FlexiSectionBlock, at least 1 branch of open FlexiSectionBlocks exists // Close open FlexiSectionBlocks that have the same or higher levels FlexiSectionBlock flexiSectionBlockToClose = null; while (currentBranch.Count > 0) { if (currentBranch.Peek().Level < flexiSectionBlock.Level) { break; } flexiSectionBlockToClose = currentBranch.Pop(); } if (flexiSectionBlockToClose != null) { processor.Close(flexiSectionBlockToClose); } // Add new FlexiSectionBlock to current stack currentBranch.Push(flexiSectionBlock); } }
internal AddBlocksAction(ContainerBlock parent) : base(parent.Root) { Param.CheckNotNull(parent); AfterChild = null; Parent = parent; }
public static void MoveBlock(ContainerBlock newParent, Block blockToMove) { using (newParent.Transaction()) { blockToMove.Delete(); newParent.AppendBlocks(blockToMove); } }
public static void MoveBlocks(ContainerBlock newParent, IEnumerable <Block> blocksToMove) { using (newParent.Transaction()) { Delete(blocksToMove); newParent.Add(blocksToMove); } }
internal AddBlocksAction(ContainerBlock parent, Block afterChild) : base(afterChild.Root) { Param.CheckNotNull(afterChild); AfterChild = afterChild; Parent = parent; }
public static AddBlocksAction AddBlocks( ContainerBlock parentBlock, IEnumerable <Block> blocksToAdd) { AddBlocksAction action = new AddBlocksAction(parentBlock); action.PrepareBlocks(blocksToAdd); return(action); }
private void RewriteContainerBlock(ContainerBlock blocks) { for (var i = 0; i < blocks.Count; i++) { var block = blocks[i]; if (block is LeafBlock leafBlock && leafBlock.Inline != null) { RewriteContainerInline(leafBlock.Inline); }
public static AddBlocksAction AddBlock( ContainerBlock parentBlock, Block toAdd) { AddBlocksAction action = new AddBlocksAction(parentBlock); action.PrepareBlocks(toAdd); return(action); }
public virtual void VisitContainer(ContainerBlock block) { foreach (Block child in block.Children) { ICSharpBlock visitable = child as ICSharpBlock; if (visitable != null) { visitable.AcceptVisitor(this); } } }
public static T FindFirstContainingBlock <T>(Block block) where T : class { ContainerBlock current = block.Parent; while (current != null && !(current is T)) { current = current.Parent; } return(current as T); }
} // proc WriteItems public void WriteItems(ContainerBlock block, bool preserveSpaces = false) { if (block == null) { throw new ArgumentNullException(nameof(block)); } WriteStartText(preserveSpaces); WriteChildren(block); WriteEndText(); } // proc WriteItems
public static ContainerBlock FindContainingMember(Block block) { ContainerBlock current = block.Parent; while (current != null && !(current is MethodBlock) && !(current is PropertyBlock)) { current = current.Parent; } return(current); }
/// <summary> /// Writes children with the specified implicit paragraphs setting. /// </summary> public static HtmlRenderer WriteChildren(this HtmlRenderer htmlRenderer, ContainerBlock containerBlock, bool implicitParagraphs) { bool initialImplicitParagraph = htmlRenderer.ImplicitParagraph; htmlRenderer.ImplicitParagraph = implicitParagraphs; htmlRenderer.WriteChildren(containerBlock); htmlRenderer.ImplicitParagraph = initialImplicitParagraph; return(htmlRenderer); }
private void SetLineNoAttributeOnAllBlocks(ContainerBlock rootBlock) { foreach (var childBlock in rootBlock) { if (childBlock is ContainerBlock) { SetLineNoAttributeOnAllBlocks(childBlock as ContainerBlock); } var attributes = childBlock.GetAttributes(); attributes.Id = childBlock.Line.ToString(); childBlock.SetAttributes(attributes); } }
public bool UnIndent() { if (this.Next == null && this.Prev != null) { ContainerBlock p = this.ParentParent; if (p != null && p.Parent != Root) { this.MoveAfterBlock(p); return(true); } } return(false); }
public bool TryValidateAncestry(ContainerBlock container, Action <string> logError) { while (container != null) { if (container is TripleColonBlock && ((TripleColonBlock)container).Extension.Name == this.Name) { logError("Zones cannot be nested."); return(false); } container = container.Parent; } return(true); }
private void VisitContainerBlock(ContainerBlock blocks) { for (var i = 0; i < blocks.Count; i++) { var block = blocks[i]; if (block is ContainerBlock containerBlock) { VisitContainerBlock(containerBlock); } var context = new BlockAggregateContext(blocks); Aggregate(context); } }
// public static CodeBlock FindContainingMember(Block block) // { // MethodBlock method = FindContainingMethod(block); // if (method != null) // { // return method; // } // // PropertyAccessorBlock accessor = FindContainingPropertyAccessor(block); // if (accessor != null) // { // return accessor.ParentProperty; // } // // return null; // } public static ContainerBlock FindContainingControlStructure(Block current) { ContainerBlock result = FindFirstContainingBlock <ControlStructureBlock>(current); if (result == null) { return(null); } if (result is DoBlock) { result = result.Parent as ContainerBlock; } return(result); }
public static void IncreaseHeadingLevel(this ContainerBlock containerBlock, int levelDiff) { if (levelDiff == 0) { return; } foreach (Block child in containerBlock) { if (child is HeadingBlock headingBlock) { headingBlock.Level += levelDiff; } } }
public void Validate(Container container) { var extensionBlocks = ContainerBlock.GetRecursivelyOfType <IExtensionBlock>(); var context = new ValidationContext(_renderSettings, Pipeline); foreach (var extensionBlock in extensionBlocks) { if (_blockErrors.ContainsKey(extensionBlock)) { // don't check for model errors if parsing didn't succeed continue; } var extensionType = _extensionByBlockType[extensionBlock.GetType()]; var extension = (IExtension)container.GetInstance(extensionType); var validator = extension.Validator; if (validator == null) { continue; } var model = _modelByBlock[extensionBlock]; IErrors validationResult = validator.Validate(model, context); if (validationResult.Errors.Any()) { _blockErrors.Add(extensionBlock, validationResult); } } var extensionInlines = ContainerBlock.GetInlinesRecursively(); foreach (var extensionInline in extensionInlines) { if (_inlineErrors.ContainsKey(extensionInline)) { // don't check for model errors if parsing didn't succeed continue; } var extensionType = _extensionByInlineType[extensionInline.GetType()]; var extension = (IExtension)container.GetInstance(extensionType); var validator = extension.Validator; if (validator == null) { continue; } var model = _modelByInline[extensionInline]; var validationResult = validator.Validate(model, context); if (validationResult.Errors.Any()) { _inlineErrors.Add(extensionInline, validationResult); } } }