Skip to content

Commit 3bdee30

Browse files
committed
Fix indentation of numbering list #166
1 parent 05d11a5 commit 3bdee30

File tree

4 files changed

+60
-9
lines changed

4 files changed

+60
-9
lines changed

src/Html2OpenXml/Expressions/Numbering/ListExpression.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ public override IEnumerable<OpenXmlElement> Interpret(ParsingContext context)
8383

8484
p.ParagraphProperties ??= new();
8585
p.ParagraphProperties.ParagraphStyleId = GetStyleIdForListItem(context.DocumentStyle, liNode);
86-
p.ParagraphProperties.Indentation = level < 2? null : new() { Left = (level * Indentation).ToString() };
8786
p.ParagraphProperties.NumberingProperties = new NumberingProperties {
8887
NumberingLevelReference = new() { Val = level - 1 },
8988
NumberingId = new() { Val = listContext.InstanceId }

src/Html2OpenXml/Expressions/Numbering/NumberingExpressionBase.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,10 @@ private static Dictionary<string, AbstractNum> InitKnownLists()
252252
LevelText = new() { Val = string.Format(text, lvlIndex+1) },
253253
LevelJustification = new() { Val = LevelJustificationValues.Left },
254254
PreviousParagraphProperties = new() {
255-
Indentation = new() { Left = Indentation.ToString(), Hanging = Indentation.ToString() }
255+
Indentation = new() {
256+
Left = ((lvlIndex + 1) * Indentation * 2).ToString(),
257+
Hanging = Indentation.ToString()
258+
}
256259
},
257260
NumberingSymbolRunProperties = useSymbol? new () {
258261
RunFonts = new() { Ascii = "Symbol", Hint = FontTypeHintValues.Default }
@@ -280,7 +283,10 @@ private static Dictionary<string, AbstractNum> InitKnownLists()
280283
StartNumberingValue = new() { Val = 1 },
281284
NumberingFormat = new() { Val = NumberFormatValues.Decimal },
282285
LevelIndex = lvlIndex,
283-
LevelText = new() { Val = lvlText.ToString() }
286+
LevelText = new() { Val = lvlText.ToString() },
287+
PreviousParagraphProperties = new() {
288+
Indentation = new() { Left = "0", Hanging = Indentation.ToString() }
289+
}
284290
});
285291
}
286292
knownAbstractNums.Add(listName, abstractNum);

src/Html2OpenXml/PredefinedStyles.resx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -359,12 +359,20 @@
359359
<data name="ListParagraph" xml:space="preserve">
360360
<value><![CDATA[<w:style w:type="paragraph" w:styleId="ListParagraph" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
361361
<w:name w:val="List Paragraph" />
362-
<w:basedOn w:val="Normal" />
363-
<w:qFormat />
362+
<w:next w:val="List Paragraph"/>
364363
<w:pPr>
365-
<w:ind w:left="720" />
364+
<w:keepNext w:val="0"/>
365+
<w:keepLines w:val="0"/>
366+
<w:spacing w:before="0" w:after="0" w:line="240" w:lineRule="auto"/>
367+
<w:ind w:left="720" w:right="0" w:firstLine="0"/>
366368
<w:contextualSpacing />
367369
</w:pPr>
370+
</w:style>]]></value>
371+
</data>
372+
<data name="Normal" xml:space="preserve">
373+
<value><![CDATA[<w:style w:type="paragraph" w:styleId="Normal" w:default="1" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
374+
<w:name w:val="Normal"/>
375+
<w:qFormat/>
368376
</w:style>]]></value>
369377
</data>
370378
<data name="Quote" xml:space="preserve">

test/HtmlToOpenXml.Tests/NumberingTests.cs

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ namespace HtmlToOpenXml.Tests
1010
[TestFixture]
1111
public class NumberingTests : HtmlConverterTestBase
1212
{
13+
const int maxLevel = 8;
14+
15+
1316
[Test(Description = "Skip any elements that is not a `li` tag")]
1417
public void NonLiElement_ShouldBeIgnored()
1518
{
@@ -181,7 +184,6 @@ public void WithExistingNumbering_ReturnsUniqueInstanceId()
181184
[Test(Description = "Word doesn't display more than 8 deep levels.")]
182185
public void MaxNumberingLevel_ShouldBeIgnored()
183186
{
184-
const int maxLevel = 8;
185187
var sb = new System.Text.StringBuilder();
186188
for (int i = 0; i <= maxLevel; i++)
187189
sb.AppendFormat("<ol><li>Item {0}", i+1);
@@ -333,16 +335,17 @@ public async Task DisableContinueNumbering_ReturnsSecondList_RestartingOrder()
333335
/// Tiered numbering such as: 1, 1.1, 1.1.1
334336
/// </summary>
335337
[Test(Description = "Nested numbering (issue #81)")]
336-
public void DecimalTieredStyle_ReturnsListWithTieredNumbering()
338+
public async Task DecimalTieredStyle_ReturnsListWithTieredNumbering()
337339
{
338-
var elements = converter.Parse(
340+
await converter.ParseBody(
339341
@"<ol style='list-style-type:decimal-tiered'>
340342
<li>Item 1
341343
<ol><li>Item 1.1</li></ol>
342344
</li>
343345
<li>Item 2</li>
344346
</ol>");
345347

348+
var elements = mainPart.Document.Body!.ChildElements;
346349
var absNum = mainPart.NumberingDefinitionsPart?.Numbering
347350
.Elements<AbstractNum>()
348351
.SingleOrDefault();
@@ -351,10 +354,15 @@ public void DecimalTieredStyle_ReturnsListWithTieredNumbering()
351354
var instances = mainPart.NumberingDefinitionsPart?.Numbering
352355
.Elements<NumberingInstance>().Where(i => i.AbstractNumId!.Val == absNum.AbstractNumberId);
353356
Assert.That(instances, Is.Not.Null);
357+
var levels = absNum.Elements<Level>();
354358
Assert.Multiple(() =>
355359
{
356360
Assert.That(instances.Count(), Is.EqualTo(1));
357361
Assert.That(instances.Select(i => i.NumberID?.HasValue), Has.All.True);
362+
Assert.That(levels.Count(), Is.EqualTo(maxLevel + 1));
363+
Assert.That(levels.Select(l => l.NumberingFormat?.Val?.Value), Has.All.EqualTo(NumberFormatValues.Decimal));
364+
Assert.That(levels.Select(l => l.PreviousParagraphProperties?.Indentation?.Left?.Value), Has.All.EqualTo("0"),
365+
"Decimal Tiered style must all be aligned on left with no indent");
358366
});
359367

360368
Assert.That(elements, Is.Not.Empty);
@@ -363,6 +371,7 @@ public void DecimalTieredStyle_ReturnsListWithTieredNumbering()
363371
e.ParagraphProperties?.NumberingProperties?.NumberingId?.Val?.Value),
364372
Has.All.EqualTo(instances.First().NumberID!.Value),
365373
"All paragraphs are linked to the same list instance");
374+
AssertThatOpenXmlDocumentIsValid();
366375
}
367376

368377
[Test(Description = "Allow to specify another start value for the first item of a `ol` list")]
@@ -503,5 +512,34 @@ public void WithRtl_ReturnsBidi(string dir, bool? expectedValue)
503512
var bidi = elements.Last().GetFirstChild<ParagraphProperties>()?.BiDi;
504513
return bidi?.Val?.Value;
505514
}
515+
516+
[Test]
517+
public void NestedNumberList_ReturnsIncrementalIdentation()
518+
{
519+
const int maxLevel = 8;
520+
var sb = new System.Text.StringBuilder();
521+
for (int i = 0; i < maxLevel; i++)
522+
sb.AppendFormat("<ol><li>Item {0}", i+1);
523+
for (int i = 0; i < maxLevel; i++)
524+
sb.Append("</li></ol>");
525+
526+
converter.Parse(sb.ToString());
527+
528+
var absNum = mainPart.NumberingDefinitionsPart?.Numbering
529+
.Elements<AbstractNum>()
530+
.SingleOrDefault();
531+
Assert.That(absNum, Is.Not.Null);
532+
533+
var levels = absNum.Elements<Level>();
534+
Assert.That(levels.Count(), Is.EqualTo(maxLevel + 1));
535+
for (int i = 0; i <= maxLevel; i++)
536+
{
537+
var level = levels.ElementAt(i);
538+
var ident = level.PreviousParagraphProperties?.Indentation;
539+
Assert.That(ident?.Hanging?.Value, Is.EqualTo("360"));
540+
Assert.That(Convert.ToInt32(ident?.Left?.Value), Is.EqualTo((i + 1) * 2 * 360));
541+
TestContext.Out.WriteLine($"{i}. {ident?.Left?.Value}");
542+
}
543+
}
506544
}
507545
}

0 commit comments

Comments
 (0)