private void EnsureParagraph(FormatContext format) { var firstParaSection = _tags .SkipWhile(t => t.Type == TagType.Span) .FirstOrDefault(); var currLevel = _tags.Count(t => t.Name == "td"); var reqLevel = format.OfType <NestingLevel>().FirstOrDefault()?.Value ?? (format.InTable ? 1 : 0); if (firstParaSection?.Type == TagType.Paragraph && _state == WriteState.Other && currLevel == reqLevel) { return; } EnsureSection(format); if (format.InTable) { var tableLevel = _tags.Count(t => t.Name == "table"); while (currLevel < reqLevel) { while (!(_tags.Peek().Name == "div" || _tags.Peek().Name == "table" || _tags.Peek().Name == "tr" || _tags.Peek().Name == "tbody" || _tags.Peek().Name == "thead" || _tags.Peek().Name == "td")) { EndTag(); } var tag = default(TagContext); if (tableLevel < reqLevel) { if (_tags.Peek().Name == "table" || _tags.Peek().Name == "tbody" || _tags.Peek().Name == "thead") { WriteTag(new TagContext("tr", _tags.PeekOrDefault())); } if (_tags.Peek().Name == "tr") { WriteTag(new TagContext("td", _tags.PeekOrDefault())); currLevel++; } } if (!(_tags.Peek().Name == "table" || _tags.Peek().Name == "tr" || _tags.Peek().Name == "tbody" || _tags.Peek().Name == "thead")) { tag = new TagContext("table", _tags.PeekOrDefault()); tag.AddRange(format.Where(t => t is CellSpacing || t is RowLeft)); WriteTag(tag); tableLevel++; var boundaries = format.OfType <ColumnBoundaries>().FirstOrDefault(); if (boundaries != null) { _writer.WriteStartElement("colgroup"); var rightBorders = boundaries .GroupBy(v => v.Value) .OrderBy(g => g.Key) .Select(g => UnitValue.Average(g.Select(k => k.Key))) .ToList(); var widths = new UnitValue[rightBorders.Count]; for (var i = 0; i < rightBorders.Count; i++) { widths[i] = i == 0 ? rightBorders[i] : rightBorders[i] - rightBorders[i - 1]; } var cells = format.OfType <CellToken>().ToList(); var everyCell = cells.Count == widths.Length || cells.Count == (widths.Length * 2); for (var i = 0; i < widths.Length; i++) { if (everyCell && cells[i].WidthUnit == CellWidthUnit.Twip) { widths[i] = new UnitValue(cells[i].Width, UnitType.Twip); } _writer.WriteStartElement("col"); _writer.WriteAttributeString("style", "width:" + TagContext.PxString(widths[i])); _writer.WriteEndElement(); } _writer.WriteEndElement(); } } if (format.OfType <HeaderRow>().Any()) { if (_tags.Peek().Name == "tbody") { EndTag(); } if (_tags.Peek().Name == "table") { WriteTag(new TagContext("thead", _tags.PeekOrDefault())); } } else if (_tags.Peek().Name == "thead") { EndTag(); WriteTag(new TagContext("tbody", _tags.PeekOrDefault())); } if (_tags.Peek().Name == "table" || _tags.Peek().Name == "tbody" || _tags.Peek().Name == "thead") { WriteTag(new TagContext("tr", _tags.PeekOrDefault())); } var cellTag = ParagraphTag("td", format); WriteTag(cellTag); var cellToken = cellTag.CellToken(); if (cellToken?.ColSpan > 1) { _writer.WriteAttributeString("colspan", cellToken.ColSpan.ToString()); } _state = WriteState.Other; currLevel++; } while (reqLevel < tableLevel) { while (_tags.Peek().Name != "table") { EndTag(); } EndTag(); tableLevel--; } } if (format.Any(IsListMarker)) { var listLevel = new KeyValuePair <int, int>( format.OfType <ListStyleId>().FirstOrDefault()?.Value ?? 1 , format.OfType <ListLevelNumber>().FirstOrDefault()?.Value ?? 0); if (listLevel.Key == _lastListLevel.Key) { while (!(_tags.Peek().Name == "div" || _tags.Peek().Name == "ul" || _tags.Peek().Name == "ol" || _tags.Peek().Name == "li" || _tags.Peek().Name == "td")) { EndTag(); } for (var i = 0; i < _lastListLevel.Value - listLevel.Value; i++) { if (_tags.Peek().Name == "li") { EndTag(); } if (_tags.Peek().Name == "ol" || _tags.Peek().Name == "ul") { EndTag(); } } if (_lastListLevel.Value >= listLevel.Value && _tags.Peek().Name == "li" && _state == WriteState.NeedListEnd) { EndTag(); } if (_lastListLevel.Value > listLevel.Value) { foreach (var keyToRemove in _listPositions.Keys .Where(k => k.Key == listLevel.Key && k.Value > listLevel.Value) .ToList()) { _listPositions.Remove(keyToRemove); } } } else { while (!(_tags.Peek().Name == "div" || _tags.Peek().Name == "td")) { EndTag(); } } _lastListLevel = listLevel; if (!_listPositions.TryGetValue(listLevel, out var startAt)) { startAt = format.OfType <NumberingStart>().FirstOrDefault()?.Value - 1 ?? 0; } _listPositions[listLevel] = ++startAt; if (!(_tags.Peek().Name == "ol" || _tags.Peek().Name == "ul")) { var numType = format.OfType <ListLevelType>().FirstOrDefault()?.Value ?? (format.OfType <NumberLevelBullet>().Any() ? (NumberingType?)NumberingType.Bullet : null) ?? format.OfType <NumberingTypeToken>().FirstOrDefault()?.Value ?? NumberingType.Bullet; var tag = new TagContext(numType == NumberingType.Bullet ? "ul" : "ol", _tags.PeekOrDefault()); tag.AddRange(format.Where(t => !IsSpanElement(t) && !(t is CapitalToken) && (t.Type == TokenType.ParagraphFormat || t.Type == TokenType.CharacterFormat))); WriteTag(tag); switch (numType) { case NumberingType.LowerLetter: _writer.WriteAttributeString("type", "a"); break; case NumberingType.LowerRoman: _writer.WriteAttributeString("type", "i"); break; case NumberingType.UpperLetter: _writer.WriteAttributeString("type", "A"); break; case NumberingType.UpperRoman: _writer.WriteAttributeString("type", "I"); break; } if (startAt > 1 && numType != NumberingType.Bullet) { _writer.WriteAttributeString("start", startAt.ToString()); } } WriteTag(ParagraphTag("li", format)); } else if (format.TryGetValue <OutlineLevel>(out var outline) && outline.Value >= 0 && outline.Value < 6) { _lastListLevel = default; var tagName = "h" + (outline.Value + 1); while (!(_tags.Peek().Name == "div" || _tags.Peek().Name == tagName || _tags.Peek().Name == "td")) { EndTag(); } WriteTag(ParagraphTag(tagName, format)); }