| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- # -*- coding: utf-8 -*-
- """Convert 9.19 markdown manuals to Word."""
- import os, re
- from docx import Document
- from docx.shared import Pt, Cm, RGBColor
- from docx.oxml.ns import qn
- from docx.enum.text import WD_ALIGN_PARAGRAPH
- from docx.enum.table import WD_TABLE_ALIGNMENT
- SRC = r"D:\产线\大洋\大洋操作手册汇总9.19"
- FONT = "微软雅黑"
- def set_run_font(run, size=11, bold=False, color=None):
- run.bold = bold
- run.font.size = Pt(size)
- run.font.name = FONT
- r = run._element
- rPr = r.get_or_add_rPr()
- rFonts = rPr.find(qn("w:rFonts"))
- if rFonts is None:
- from lxml import etree
- rFonts = rPr.makeelement(qn("w:rFonts"), {})
- rPr.append(rFonts)
- rFonts.set(qn("w:eastAsia"), FONT)
- rFonts.set(qn("w:ascii"), FONT)
- rFonts.set(qn("w:hAnsi"), FONT)
- if color:
- run.font.color.rgb = RGBColor(*color)
- def add_runs(p, text, size=11, bold=False):
- # split **bold**
- parts = re.split(r"(\*\*[^*]+\*\*)", text)
- for part in parts:
- if part.startswith("**") and part.endswith("**"):
- run = p.add_run(part[2:-2])
- set_run_font(run, size=size, bold=True)
- else:
- run = p.add_run(part)
- set_run_font(run, size=size, bold=bold)
- def parse_table(lines, i):
- rows = []
- while i < len(lines) and lines[i].startswith("|"):
- raw = [c.strip() for c in lines[i].strip().strip("|").split("|")]
- if not re.match(r"^:?-+:?$", raw[0].replace(" ", "")):
- rows.append(raw)
- i += 1
- return rows, i
- def convert(md_path, docx_path):
- text = open(md_path, encoding="utf-8").read()
- lines = text.splitlines()
- doc = Document()
- section = doc.sections[0]
- section.top_margin = Cm(2)
- section.bottom_margin = Cm(2)
- section.left_margin = Cm(2.2)
- section.right_margin = Cm(2.2)
- style = doc.styles["Normal"]
- style.font.name = FONT
- style.font.size = Pt(11)
- style.element.rPr.rFonts.set(qn("w:eastAsia"), FONT)
- i = 0
- while i < len(lines):
- line = lines[i].rstrip()
- if not line:
- i += 1
- continue
- if line.startswith("# "):
- p = doc.add_heading("", level=0)
- p.clear()
- run = p.add_run(line[2:].strip())
- set_run_font(run, size=18, bold=True, color=(0x1F, 0x4E, 0x79))
- i += 1
- continue
- if line.startswith("## "):
- p = doc.add_heading("", level=1)
- p.clear()
- run = p.add_run(line[3:].strip())
- set_run_font(run, size=16, bold=True, color=(0x2E, 0x75, 0xB6))
- i += 1
- continue
- if line.startswith("### "):
- p = doc.add_heading("", level=2)
- p.clear()
- run = p.add_run(line[4:].strip())
- set_run_font(run, size=14, bold=True, color=(0x2E, 0x75, 0xB6))
- i += 1
- continue
- if line.startswith("#### "):
- p = doc.add_heading("", level=3)
- p.clear()
- run = p.add_run(line[5:].strip())
- set_run_font(run, size=12, bold=True)
- i += 1
- continue
- if line.startswith("---"):
- i += 1
- continue
- if line.startswith("|"):
- rows, i = parse_table(lines, i)
- if rows:
- cols = max(len(r) for r in rows)
- table = doc.add_table(rows=len(rows), cols=cols)
- table.style = "Table Grid"
- table.alignment = WD_TABLE_ALIGNMENT.CENTER
- for r_idx, row in enumerate(rows):
- for c_idx in range(cols):
- cell = table.cell(r_idx, c_idx)
- cell.text = ""
- p = cell.paragraphs[0]
- val = row[c_idx] if c_idx < len(row) else ""
- add_runs(p, val, size=10, bold=(r_idx == 0))
- continue
- if line.startswith("- "):
- p = doc.add_paragraph(style="List Bullet")
- p.clear()
- add_runs(p, line[2:].strip())
- i += 1
- continue
- if re.match(r"^\d+\.\s", line):
- p = doc.add_paragraph(style="List Number")
- p.clear()
- add_runs(p, re.sub(r"^\d+\.\s", "", line))
- i += 1
- continue
- p = doc.add_paragraph()
- add_runs(p, line)
- i += 1
- doc.save(docx_path)
- print("saved", os.path.basename(docx_path))
- def main():
- files = [f for f in os.listdir(SRC) if f.endswith(".md")]
- files.sort()
- for f in files:
- md = os.path.join(SRC, f)
- docx = os.path.join(SRC, os.path.splitext(f)[0] + ".docx")
- convert(md, docx)
- if __name__ == "__main__":
- main()
|