Skip to content

Commit 59a0a97

Browse files
committed
feat: add support for bold list text in DOCX to PDF conversion
1 parent fac6c67 commit 59a0a97

8 files changed

Lines changed: 15 additions & 8 deletions

File tree

src/MiniPdf/DocxReader.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,7 @@ internal static DocxDocument Read(Stream stream)
451451
bool snapToGrid = true;
452452
int listLevel = 0;
453453
string? listText = null;
454+
bool listTextBold = false;
454455
string? styleId = null;
455456
bool bold = false;
456457
bool italic = false;
@@ -562,6 +563,7 @@ internal static DocxDocument Read(Stream stream)
562563
var lvlDef = numDef.Levels.FirstOrDefault(l => l.Ilvl == listLevel) ?? numDef.Levels.FirstOrDefault();
563564
if (lvlDef != null)
564565
{
566+
if (lvlDef.Bold) listTextBold = true;
565567
if (indentLeft == 0 && lvlDef.IndentLeft > 0)
566568
indentLeft = lvlDef.IndentLeft;
567569
if (indentFirstLine == 0 && lvlDef.Hanging > 0)
@@ -855,7 +857,7 @@ internal static DocxDocument Read(Stream stream)
855857
// If paragraph has no runs and no images, represent as empty paragraph for spacing
856858
return new DocxParagraph(runs, images, alignment, spacingBefore, spacingAfter,
857859
lineSpacing, lineSpacingAbsolute, lineSpacingExact, indentLeft, indentRight, indentFirstLine,
858-
isBulletList, isNumberedList, listLevel, listText, styleId,
860+
isBulletList, isNumberedList, listLevel, listText, listTextBold, styleId,
859861
bold, italic, fontSize, color, pageBreakBefore, pageBreakAfter, paragraphShading, tabStops,
860862
sectionBreakLayout, borders, shapes.Count > 0 ? shapes : null,
861863
ContextualSpacing: contextualSpacing, SnapToGrid: snapToGrid,
@@ -3410,8 +3412,12 @@ private static Dictionary<string, DocxNumberingDef> ReadNumbering(ZipArchive arc
34103412
lvlHanging = lh / 20f;
34113413
}
34123414
// Read bullet font name from rPr/rFonts (e.g. Wingdings, Symbol)
3413-
var lvlFontName = lvl.Element(W + "rPr")?.Element(W + "rFonts")?.Attribute(W + "ascii")?.Value;
3414-
levels.Add(new DocxNumberingLevelDef(ilvl, numFmt, lvlText, startVal, lvlIndentLeft, lvlHanging, lvlFontName));
3415+
var lvlRPr = lvl.Element(W + "rPr");
3416+
var lvlFontName = lvlRPr?.Element(W + "rFonts")?.Attribute(W + "ascii")?.Value;
3417+
// Read bold from numbering level rPr (used for list label rendering)
3418+
var lvlBoldEl = lvlRPr?.Element(W + "b");
3419+
var lvlBold = lvlBoldEl != null && lvlBoldEl.Attribute(W + "val")?.Value is not ("0" or "false");
3420+
levels.Add(new DocxNumberingLevelDef(ilvl, numFmt, lvlText, startVal, lvlIndentLeft, lvlHanging, lvlFontName, lvlBold));
34153421
}
34163422
abstractDefs[absId] = levels;
34173423
}
@@ -3496,6 +3502,7 @@ internal sealed record DocxParagraph(
34963502
bool IsNumberedList = false,
34973503
int ListLevel = 0,
34983504
string? ListText = null,
3505+
bool ListTextBold = false,
34993506
string? StyleId = null,
35003507
bool Bold = false,
35013508
bool Italic = false,
@@ -3833,4 +3840,4 @@ private static string ToRoman(int num)
38333840
}
38343841
}
38353842

3836-
internal sealed record DocxNumberingLevelDef(int Ilvl, string NumFmt, string LvlText, int Start, float IndentLeft = 0, float Hanging = 0, string? FontName = null);
3843+
internal sealed record DocxNumberingLevelDef(int Ilvl, string NumFmt, string LvlText, int Start, float IndentLeft = 0, float Hanging = 0, string? FontName = null, bool Bold = false);

src/MiniPdf/DocxToPdfConverter.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,7 +1025,7 @@ private static void RenderParagraph(RenderState state, DocxParagraph paragraph)
10251025
{
10261026
// Hanging indent from DOCX: number at outdented position, body text at indentLeft
10271027
var numberX = options.MarginLeft + paragraph.IndentLeft + paragraph.IndentFirstLine;
1028-
state.CurrentPage!.AddText(paragraph.ListText, numberX, state.CurrentY, fontSize, preferredFontName: listFont);
1028+
state.CurrentPage!.AddText(paragraph.ListText, numberX, state.CurrentY, fontSize, preferredFontName: listFont, bold: paragraph.ListTextBold);
10291029
// x and availableWidth remain unchanged (body text wraps at indentLeft)
10301030
}
10311031
else
@@ -1036,13 +1036,13 @@ private static void RenderParagraph(RenderState state, DocxParagraph paragraph)
10361036
// Style already provides left indentation (e.g. ListParagraph)
10371037
// Place the label to the left of the text body without reducing available width
10381038
var numberX = options.MarginLeft + Math.Max(0, paragraph.IndentLeft - 18f);
1039-
state.CurrentPage!.AddText(paragraph.ListText, numberX, state.CurrentY, fontSize, preferredFontName: listFont);
1039+
state.CurrentPage!.AddText(paragraph.ListText, numberX, state.CurrentY, fontSize, preferredFontName: listFont, bold: paragraph.ListTextBold);
10401040
// x and availableWidth remain unchanged (indentLeft already accounts for list)
10411041
}
10421042
else
10431043
{
10441044
var listIndent = 18f * (paragraph.ListLevel + 1);
1045-
state.CurrentPage!.AddText(paragraph.ListText, x + listIndent - 12f, state.CurrentY, fontSize, preferredFontName: listFont);
1045+
state.CurrentPage!.AddText(paragraph.ListText, x + listIndent - 12f, state.CurrentY, fontSize, preferredFontName: listFont, bold: paragraph.ListTextBold);
10461046
x += listIndent;
10471047
availableWidth -= listIndent;
10481048
}
@@ -1237,7 +1237,7 @@ private static void RenderParagraph(RenderState state, DocxParagraph paragraph)
12371237
paragraph.SpacingBefore, paragraph.SpacingAfter, paragraph.LineSpacing, paragraph.LineSpacingAbsolute,
12381238
paragraph.LineSpacingExact, paragraph.IndentLeft, paragraph.IndentRight, paragraph.IndentFirstLine,
12391239
paragraph.IsBulletList, paragraph.IsNumberedList, paragraph.ListLevel, paragraph.ListText,
1240-
paragraph.StyleId, paragraph.Bold, paragraph.Italic, paragraph.FontSize, paragraph.Color,
1240+
paragraph.ListTextBold, paragraph.StyleId, paragraph.Bold, paragraph.Italic, paragraph.FontSize, paragraph.Color,
12411241
paragraph.HasPageBreakBefore, paragraph.HasPageBreakAfter, paragraph.Shading, paragraph.TabStops,
12421242
paragraph.SectionBreak, paragraph.Borders),
12431243
x, firstLineX, wrapAvailableWidth, wrapFirstLineWidth, fontSize, lineHeight);
-131 Bytes
Loading
-167 Bytes
Loading
533 Bytes
Loading
-96 Bytes
Loading
-9.89 KB
Loading
11.1 KB
Loading

0 commit comments

Comments
 (0)