“Brush” the format of one template docx onto another docx. Core idea:Format parameters are measured from the template and converge to a single output for application, manual adjustment by feel will inevitably be inconsistent.
Applicable scenarios
- Repair scenario: A docx whose content is correct but whose format is messy (typical: output converted by pandoc / other models), unify the format according to the template
- New creation scenario: Generate a docx from scratch, requiring the format to be consistent with a certain template
- Diagnosis scenario: Only want to know where the format differences between two docx files are
Three-step workflow
Step 1: Dissect the template → format fingerprint
python3 scripts/extract_fingerprint.py "模板.docx"
Output the template's format fingerprint (JSON + readable summary):
- Font, eastAsia Chinese font, font size, bold, color of each style (Normal/Heading 1-3/Body Text)
- Measured line spacing, first-line indent, alignment distribution of body paragraphs (take the mode as the standard; style definitions often do not match the actual runs)
- Measured parameters of heading paragraphs (template authors often override styles at the run level, so run-level measurements must be used as the standard)
- Cover page paragraph structure (font size/alignment of the first 3 paragraphs)
- Tables: presence or absence of borders, cell font and font size
- Whether chapter titles start on a new page (pageBreakBefore)
Why measure rather than only looking at the style sheet: Chinese official document docx files almost always set fonts such as FangSong directly at the run level, while the style sheet may still contain default values. Trusting only the style sheet will inevitably brush incorrectly.
Step 2: Diagnose the target file (repair scenario)
python3 scripts/extract_fingerprint.py "目标.docx"
Compare the two fingerprints and list the problems. Typical problems in pandoc output:
- All run fonts/font sizes are None (barely inheriting Body Text/First Paragraph default styles → mixed Calibri/SimSun)
- Headings have the default theme blue (0F4761)
- Tables have no tblBorders (no borders)
- No cover page, chapters do not start on a new page
- Chinese quotation marks are reversed in opening/closing (
"xxx"converted to”xxx“)
Step 3: Apply the format brush
python3 scripts/apply_format.py "目标.docx" --config fingerprint.json [--out "输出.docx"]
Without --out , repair in place. The script applies in five layers in order (order matters: the style layer provides the fallback first, then the run layer precisely overrides):
- Style layer: Change Normal/Body Text/First Paragraph/Heading 1-3 all to the template font and font size, clear colors — covering all inheritance
- Paragraph layer: Unify line spacing/first-line indent for body text; clear indentation for headings, set font size and bold according to the fingerprint;
第X章type Heading 1 centered + pageBreakBefore - Cover page layer: When the first paragraph contains keywords such as "document/report/plan", redo the three-line cover page (company name/project name in large font size + document type in even larger font size, centered and bold)
- Table layer: Fill in single-line tblBorders, unify cell font and font size, bold the header row, line spacing 1.0, clear indentation
- Text layer:Chinese quotation marks are reordered by opening/closing pairing as
“xxx”
Key technical points (must-read before writing any docx processing code)
- Chinese fonts must be set twice:
run.font.nameonly handles Western text; you must also setrPr.rFonts.set(qn('w:eastAsia'), '仿宋'), otherwise Word falls back to SimSun for Chinese - Font size conversion:docx internally uses EMU,
磅 = EMU / 12700(e.g. 152400 = 12 pt, 203200 = 16 pt) - First-line indent of 2 characters ≈ Emu(304800) (12 pt body text) or Emu(406400) (16 pt body text), i.e. 2× the font size
- Clearing color:
r.font.color.rgb = Noneis not enough; you need to remove from rPr thew:colorelement - Section page break:insert into pPr the
w:pageBreakBeforeelement, which is preferable to inserting a page break run - New document scenario:first prepare structured content JSON, then call
scripts/gen_from_template.py. Within the script, thetitle()、para()andtable()factories uniformly apply the fingerprint parameters; all content is written only through the factory functions.
python3 scripts/gen_from_template.py "content.json" \
--config fingerprint.json \
--out "output/doc/输出.docx"
The content JSON uses cover and blocks。blocks support heading、paragraph、table、page_break; see the explanation at the top of the script for a complete example.
Verification (mandatory; not complete until done)
python3 scripts/verify_format.py "输出.docx"
Pass criteria:
- The run font distribution converges to the few tiers specified by the fingerprint (e.g. FangSong 12/15/22 pt), with no None and no stray colors
- All tables have tblBorders
- All
第X章Heading 1 have pageBreakBefore - Spot-check that paragraphs containing quotation marks have the correct direction
Show the verification output to the user, and report the "problem → fix" comparison in a table.
Output conventions
- For fix scenarios, save in place by default, and also place a copy in the directory previously requested by the user
- New document scenario output to
output/doc/ - When reporting, list the format fingerprint table (element/parameter) so the user can verify it