12 KiB
Executable File
FAQ — Common Bugs and Fixes
Bug: Table text touching cell borders
Symptom: Text is cramped against table cell edges, no padding.
Fix: Set margins at the TableCell level:
new TableCell({
margins: { top: 60, bottom: 60, left: 120, right: 120 },
children: [/* ... */],
})
Bug: Numbered list doesn't restart
Symptom: Second numbered list continues from where the first left off (e.g., starts at 4 instead of 1).
Fix: Each separate numbered list MUST use a unique reference name in numbering config:
numbering: { config: [
{ reference: "list-A", levels: [{ level: 0, format: LevelFormat.DECIMAL, text: "%1." }] },
{ reference: "list-B", levels: [{ level: 0, format: LevelFormat.DECIMAL, text: "%1." }] },
]}
Bug: Cover and content on same page
Symptom: Cover page content flows directly into main content without page break.
Fix: Add a PageBreak paragraph at the end of cover content:
coverChildren.push(new Paragraph({ children: [new PageBreak()] }));
Bug: Three-line table shows all borders
Symptom: Table intended to be three-line shows full grid borders.
Fix: Set table-level borders to NONE, then override only specific cell borders:
// Table level: all borders NONE
borders: { top: { style: BorderStyle.SINGLE, size: 4 }, bottom: { style: BorderStyle.SINGLE, size: 4 },
left: { style: BorderStyle.NONE }, right: { style: BorderStyle.NONE },
insideHorizontal: { style: BorderStyle.NONE }, insideVertical: { style: BorderStyle.NONE } }
// Header cells: bottom border only
headerCell.borders = { bottom: { style: BorderStyle.SINGLE, size: 2, color: "000000" } }
Bug: User requests Chinese font size name (e.g. Wu Hao) but output is wrong
Symptom: Font size doesn't match expected Chinese size name.
Fix: Use the correct half-point value. size in docx-js is in half-points:
- Wu Hao 五号 = 10.5pt →
size: 21 - Xiao Si 小四 = 12pt →
size: 24 - Si Hao 四号 = 14pt →
size: 28
See SKILL.md for complete conversion table.
Bug: Black table cells
Symptom: Table cells appear solid black in Word.
Fix: Use ShadingType.CLEAR not ShadingType.SOLID:
// ❌ WRONG
shading: { type: ShadingType.SOLID, fill: "F1F5F9" }
// ✅ CORRECT
shading: { type: ShadingType.CLEAR, fill: "F1F5F9" }
Bug: Chinese characters garbled in matplotlib charts
Symptom: Chinese text shows as empty boxes □□□ in generated PNG charts.
Fix: Configure SimHei font before plotting:
from matplotlib.font_manager import FontProperties
zh_font = FontProperties(fname="/path/to/SimHei.ttf")
plt.title("中文标题", fontproperties=zh_font)
plt.rcParams["axes.unicode_minus"] = False
Bug: Image stretched/squashed in document
Symptom: Embedded image appears distorted.
Fix: Calculate display height from width using original aspect ratio:
const aspectRatio = originalHeight / originalWidth;
const displayWidth = 500;
const displayHeight = Math.round(displayWidth * aspectRatio);
new ImageRun({ data: buf, transformation: { width: displayWidth, height: displayHeight }, type: "png" });
Bug: TOC shows empty in generated document
→ See references/toc.md — "5 Common TOC Bugs" section for diagnosis and fixes.
Bug: PageBreak standalone crashes Word
Symptom: Document fails to open or renders incorrectly.
Fix: PageBreak must always be wrapped in a Paragraph:
// ❌ WRONG — standalone
children: [new PageBreak()]
// ✅ CORRECT — inside Paragraph
children: [new Paragraph({ children: [new PageBreak()] })]
Bug: Quotation marks break JavaScript syntax — ⚠️ #1 MOST COMMON BUG
This is the single most frequent code generation error. Chinese text routinely uses curly quotes "" for emphasis, proper nouns, and event names (e.g., "双11", "前低后高", "618"大促). These MUST be Unicode-escaped — bare curly quotes silently break JS syntax.
Rule: scan ALL Chinese text for ""'' and replace with \u201c \u201d \u2018 \u2019 BEFORE writing the string.
// ❌ WRONG — curly quotes in Chinese text break syntax (extremely common)
para("行业增速呈现"前低后高"的态势,在"618"大促拉动下增长。")
"他说"你好"" // \u201c \u201d
'It's a test' // \u2019
// ✅ CORRECT — Unicode escapes for ALL curly quotes
para("行业增速呈现\u201c前低后高\u201d的态势,在\u201c618\u201d大促拉动下增长。")
"他说\u201c你好\u201d"
"It\u2019s a test"
// ✅ Straight quotes: escape or use alternate delimiters
"He said \"hello\""
'He said "hello"'
Bug: Unwanted blank pages in document
Common causes:
- Trailing PageBreak at end of last section — pagination should use section breaks or be at the start of the next section
- Empty Paragraph overflow — empty paragraphs at page bottom push to a new page
- PageBreak right after Table — Table already at page bottom, PageBreak creates extra page
Fix:
// Post-generation check: last section's children should not end with PageBreak
function removeTrailingPageBreak(section) {
const children = section.children;
if (!children.length) return;
const last = children[children.length - 1];
// If last element is a Paragraph containing only PageBreak, remove it
if (last instanceof Paragraph) {
const runs = last.root?.filter(c => c instanceof PageBreak);
if (runs?.length && !last.root?.some(c => c instanceof TextRun)) {
children.pop();
}
}
}
Prevention rules:
- Place PageBreak at the start of the next section, not the end of the previous one
- Or use separate sections for pagination (no PageBreak needed)
- The last section of a document must NEVER end with a PageBreak
Bug: Different rendering in WPS vs Microsoft Word
Symptom: Document looks correct in Word but renders differently in WPS (or vice versa) — misaligned tables, shifted content, clipped text in cells, black cells, or broken covers.
Root causes and fixes:
1. ShadingType.SOLID shows black in WPS
// ❌ WPS shows solid black
shading: { type: ShadingType.SOLID, fill: "F1F5F9" }
// ✅ Both renderers show correct color
shading: { type: ShadingType.CLEAR, fill: "F1F5F9" }
2. verticalAlign: "center" in exact-height rows shifts content
WPS ignores vertical centering in rule: "exact" rows — content stays at top, creating visual mismatch.
// ❌ Inconsistent between Word and WPS
new TableRow({ height: { value: 800, rule: "exact" },
children: [new TableCell({ verticalAlign: VerticalAlign.CENTER, ... })] })
// ✅ Use top alignment + margins/spacing for positioning
new TableRow({ height: { value: 800, rule: "exact" },
children: [new TableCell({ verticalAlign: VerticalAlign.TOP,
margins: { top: 200 }, ... })] })
3. Tab stops misalign in WPS
Tab widths differ between Word and WPS. Never use tabs for alignment.
// ❌ Tab-based alignment — breaks in WPS
new Paragraph({ tabStops: [{ type: TabStopType.RIGHT, position: 8000 }],
children: [new TextRun({ text: "Party A:\tCompany Name" })] })
// ✅ Borderless table for alignment — consistent everywhere
new Table({ borders: allNoBorders, rows: [new TableRow({ children: [
new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: "Party A:" })] })] }),
new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: "Company Name" })] })] }),
] })] })
4. Nested tables in exact-height cells overflow differently
Word calculates nested table heights more accurately than WPS. Use stacked tables instead.
// ❌ Nested table inside exact-height cell
new TableRow({ height: { value: 16838, rule: "exact" },
children: [new TableCell({ children: [nestedTable1, nestedTable2] })] })
// ✅ Stacked approach — content table + filler table
[contentTable, fillerTable] // both at top level, heights sum to 16838
5. characterSpacing renders differently
Large characterSpacing values cause inconsistent letter spacing. Keep ≤ 80.
6. titlePage: true header/footer suppression
WPS may not correctly hide first-page headers when using titlePage: true. Use a separate section for the cover instead.
Bug: Cover spills to second page
Symptom: Cover content overflows, with some elements (date, footer, accent strip) appearing on page 2.
Root cause: Total content height exceeds 16838 twips (A4 page height). Common when:
- Title is very long (3+ lines at large font size)
- Fixed spacing values assume short title
- Multiple meta lines + subtitle + English label
Fix: Always use calcTitleLayout() + calcCoverSpacing() from design-system.md. These dynamically adjust font sizes and spacing to fit within the page. See design-system.md § Cover Content Overflow Prevention for the complete checklist.
Bug: Blank page 2 after cover in MS Office (but not WPS)
Symptom: Cover displays correctly in WPS but produces a blank second page in MS Office Word.
Root cause: The cover wrapper table uses default docx-js table borders (single/auto/sz=4) instead of explicitly setting allNoBorders. Default borders add ~8 twips per edge. MS Office includes border thickness in the exact-height row calculation, pushing total height past 16838 twips → overflow to page 2. WPS is more lenient and absorbs the extra pixels.
Fix: Every cover wrapper table MUST explicitly set borders: allNoBorders:
const NB = { style: BorderStyle.NONE, size: 0, color: "FFFFFF" };
const allNoBorders = { top: NB, bottom: NB, left: NB, right: NB,
insideHorizontal: NB, insideVertical: NB };
new Table({
borders: allNoBorders, // ← MANDATORY
rows: [new TableRow({
height: { value: 16838, rule: "exact" },
// ...
})],
});
Prevention: Add to post-generation check — search for any new Table in cover code that does not explicitly set borders.
Bug: Cover decorative lines appear truncated or misaligned
Symptom: Horizontal decorative lines on the cover (accent strips, divider rules) display at different widths in MS Office vs WPS, or appear truncated / not spanning the intended width.
Root cause: Lines were implemented using text characters (───, ━━━, ═══, ——————) instead of paragraph borders. Character-drawn lines depend on font metrics (character width × count), which vary across rendering engines.
Fix: Always use paragraph borders for decorative lines:
// ✅ Paragraph border — renders consistently in both MS Office and WPS
new Paragraph({
indent: { left: 1000, right: 1000 },
border: { top: { style: BorderStyle.SINGLE, size: 18, color: accentColor, space: 20 } },
children: [],
})
// ❌ NEVER use text characters for decorative lines
new TextRun({ text: "───────────────" }) // width varies across engines
Note: This applies to ALL cover recipes (R1–R5). Recipe R2 uses border.top and border.bottom for its double-rule frame — follow this pattern.
Bug: "undefined" appears in document text
Symptom: Fields like "Contact: undefined" or "Location: undefined" in generated documents.
Root cause: JavaScript outputs the string "undefined" when accessing a property that doesn't exist on the config object.
Fix: Use safeText() helper for ALL user-facing text values:
function safeText(value, placeholder) {
if (value === undefined || value === null || value === "" ||
String(value) === "NaN" || String(value) === "undefined") {
return placeholder || "【Please fill in】";
}
return String(value);
}
// Usage: new TextRun({ text: safeText(config.contact, "【Contact person】") })