/// <summary> /// Opens a <see cref="ProxyTableBlock"/> if a line is a column definitions line. /// </summary> /// <param name="blockProcessor">The <see cref="BlockProcessor"/> for the document that contains a line starting with '+'.</param> /// <returns> /// <see cref="BlockState.None"/> if the current line has code indent. /// <see cref="BlockState.None"/> if the current line is not a column definitions line. /// <see cref="BlockState.ContinueDiscard"/> if a <see cref="ProxyTableBlock"/> is opened. /// </returns> protected override BlockState TryOpenBlock(BlockProcessor blockProcessor) { // A grid table cannot start more than an indent if (blockProcessor.IsCodeIndent) { return(BlockState.None); } // Check if line is a column definitions line, parses column definitions if it is List <ColumnDefinition> columnDefinitions; if ((columnDefinitions = TryParseColumnDefinitionsLine(blockProcessor.Line, '+', -1)) == null) { return(BlockState.None); } // Create ProxyTableBlock ProxyTableBlock proxyTableBlock = _flexiTableBlockFactory.CreateProxy(blockProcessor, this); proxyTableBlock.ColumnDefinitions = columnDefinitions; proxyTableBlock.NumColumns = columnDefinitions.Count; blockProcessor.NewBlocks.Push(proxyTableBlock); // Store current line in case the grid FlexiTableBlock is invalid proxyTableBlock.Lines.Add(blockProcessor.Line); return(BlockState.ContinueDiscard); }
internal virtual FlexiTableBlock CreateFlexiTableBlock(string blockName, FlexiTableType type, ReadOnlyDictionary <string, string> attributes, ProxyTableBlock proxyTableBlock, BlockProcessor blockProcessor) { // Create table block var flexiTableBlock = new FlexiTableBlock(blockName, type, attributes, proxyTableBlock.Parser) { Column = proxyTableBlock.Column, Line = proxyTableBlock.Line, Span = proxyTableBlock.Span }; // Create row blocks bool headerRowFound = false; BlockProcessor childBlockProcessor = blockProcessor.CreateChild(); List <Row> rows = proxyTableBlock.Rows; List <ColumnDefinition> columnDefinitions = proxyTableBlock.ColumnDefinitions; int numColumns = proxyTableBlock.NumColumns; int numRows = rows.Count; bool typeIsUnresponsive = type == FlexiTableType.Unresponsive; for (int rowIndex = 0; rowIndex < numRows; rowIndex++) { Row row = rows[rowIndex]; bool isHeaderRow = row.IsHeaderRow; if (!typeIsUnresponsive && isHeaderRow) { if (headerRowFound) { throw new OptionsException(nameof(IFlexiTableBlockOptions.Type), Strings.OptionsException_FlexiTableBlockFactory_TypeInvalidForTablesWithMultipleHeaderRows); } headerRowFound = true; } // Create and add row flexiTableBlock.Add(CreateFlexiTableRowBlock(type, childBlockProcessor, columnDefinitions, numColumns, rowIndex, row, isHeaderRow)); } // Release for reuse childBlockProcessor.ReleaseChild(); return(flexiTableBlock); }
/// <inheritdoc /> public FlexiTableBlock Create(ProxyTableBlock proxyTableBlock, BlockProcessor blockProcessor) { (IFlexiTableBlockOptions flexiTableBlockOptions, IFlexiTableBlocksExtensionOptions _) = _optionsService. CreateOptions(blockProcessor); // Block name string blockName = ResolveBlockName(flexiTableBlockOptions.BlockName); // Type FlexiTableType type = flexiTableBlockOptions.Type; ValidateType(type); // Create block return(CreateFlexiTableBlock(blockName, type, flexiTableBlockOptions.Attributes, proxyTableBlock, blockProcessor)); }
/// <summary> /// Opens a <see cref="ProxyTableBlock"/> if a line is a column definitions line or a row line. /// </summary> /// <param name="blockProcessor">The <see cref="BlockProcessor"/> for the document that contains a line starting with '|'.</param> /// <returns> /// <see cref="BlockState.None"/> if the current line has code indent. /// <see cref="BlockState.None"/> if the current line is neither a column definitions line nor a row line. /// <see cref="BlockState.ContinueDiscard"/> if a <see cref="ProxyTableBlock"/> is opened. /// </returns> protected override BlockState TryOpenBlock(BlockProcessor blockProcessor) { // A grid table cannot start more than an indent if (blockProcessor.IsCodeIndent) { return(BlockState.None); } // Parse line Row row = null; StringSlice line = blockProcessor.Line; List <ColumnDefinition> columnDefinitions; if ((columnDefinitions = TryParseColumnDefinitionsLine(line, '|', -1)) == null && (row = TryParseRowLine(blockProcessor, 0, -1)) == null) { return(BlockState.None); } // Create ProxyTableBlock ProxyTableBlock proxyTableBlock = _flexiTableBlockFactory.CreateProxy(blockProcessor, this); if (columnDefinitions != null) { proxyTableBlock.ColumnDefinitions = columnDefinitions; proxyTableBlock.NumColumns = columnDefinitions.Count; } else { proxyTableBlock.Rows.Add(row); proxyTableBlock.NumColumns = row.Count; } blockProcessor.NewBlocks.Push(proxyTableBlock); // Store current line in case the grid FlexiTableBlock is invalid proxyTableBlock.Lines.Add(line); return(BlockState.ContinueDiscard); }
/// <summary> /// Continues a <see cref="ProxyTableBlock"/> if the current line is a column definitions line or a row line. /// </summary> /// <param name="blockProcessor">The <see cref="BlockProcessor"/> for the <see cref="ProxyTableBlock"/> to try continuing.</param> /// <param name="block">The <see cref="ProxyTableBlock"/> to try continuing.</param> /// <returns> /// <see cref="BlockState.Break"/> if the current line does not start with '|'. This closes the <see cref="ProxyTableBlock"/>. /// <see cref="BlockState.Break"/> if the current line starts with '|' but is not a column definitions line or row line. The <see cref="ProxyTableBlock"/> is replaced with a paragraph block. /// <see cref="BlockState.ContinueDiscard"/> if the <see cref="ProxyTableBlock"/> remains open. /// </returns> protected override BlockState TryContinueBlock(BlockProcessor blockProcessor, ProxyTableBlock block) { if (blockProcessor.CurrentChar != '|') // No longer in table { return(BlockState.Break); } // Parse line StringSlice line = blockProcessor.Line; List <Row> rows = block.Rows; bool undo = true; int numColumns = block.NumColumns; List <ColumnDefinition> columnDefinitions; if (block.ColumnDefinitions == null && (columnDefinitions = TryParseColumnDefinitionsLine(line, '|', numColumns)) != null) { undo = false; block.ColumnDefinitions = columnDefinitions; foreach (Row headerRow in rows) { headerRow.IsHeaderRow = true; } } Row row; if (undo && (row = TryParseRowLine(blockProcessor, rows.Count, numColumns)) != null) { undo = false; rows.Add(row); } if (undo) { Undo(blockProcessor, block); return(BlockState.Break); } // Update span end block.UpdateSpanEnd(line.End); // Store current line in case the grid FlexiTableBlock is invalid block.Lines.Add(line); return(BlockState.ContinueDiscard); }
/// <summary> /// Continues a <see cref="ProxyTableBlock"/> if the current line is a content line or a separator line. /// </summary> /// <param name="blockProcessor">The <see cref="BlockProcessor"/> processing the <see cref="ProxyTableBlock"/> to try continuing.</param> /// <param name="block">The <see cref="ProxyTableBlock"/> to try continuing.</param> /// <returns> /// <see cref="BlockState.Break"/> if the current line does not start with '|' or '+'. This closes the <see cref="ProxyTableBlock"/>. /// <see cref="BlockState.Break"/> if the current line starts with '|' or '+' but is not a content line or separator line. The <see cref="ProxyTableBlock"/> is replaced with a paragraph block. /// <see cref="BlockState.ContinueDiscard"/> if the <see cref="ProxyTableBlock"/> remains open. /// </returns> protected override BlockState TryContinueBlock(BlockProcessor blockProcessor, ProxyTableBlock block) { // Parse line bool undo; if (blockProcessor.CurrentChar == '|') // Content line { undo = !TryParseContentLine(blockProcessor, block); } else if (blockProcessor.CurrentChar == '+') // Row separator line { undo = !TryParseSeparatorLine(blockProcessor.Line, block); } else // No longer in table { return(BlockState.Break); } if (undo) { Undo(blockProcessor, block); return(BlockState.Break); } // Update span end block.UpdateSpanEnd(blockProcessor.Line.End); // Store current line in case the grid FlexiTableBlock is invalid block.Lines.Add(blockProcessor.Line); return(BlockState.ContinueDiscard); }
// A content line is <content> one or more times followed by '|'. // <content> is '|' followed by a series of characters, where '|' is aligned with a '+' in the column definitions line. // // Example content lines: | content | internal virtual bool TryParseContentLine(BlockProcessor blockProcessor, ProxyTableBlock proxyTableBlock) { ref StringSlice line = ref blockProcessor.Line;