# Markdown to DOCX (any2docx)

Convert Markdown to professionally styled, editable Word documents with python-docx. Same theme palette as any2pdf. Supports image embedding (local + remote URLs), auto-refresh TOC, and watermarks.

## Prerequisites

```bash
pip install python-docx Pillow requests python-dotenv
```

## Usage

Generate the conversion script, then run:

```bash
python3 md2docx.py --input report.md --output report.docx --theme warm-academic
```

**Note**: The agent generates a tailored conversion script on first use. Below are the key implementation patterns with python-docx.

### Core: Document Setup & Theme

```python
from docx import Document
from docx.shared import Pt, Inches, Cm, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT
from docx.oxml.ns import qn
import os, requests

doc = Document()

# Page margins
for section in doc.sections:
    section.top_margin = Cm(2.5)
    section.bottom_margin = Cm(2.0)
    section.left_margin = Cm(2.5)
    section.right_margin = Cm(2.5)

# Theme colors (warm-academic example)
ACCENT = RGBColor(0x8B, 0x45, 0x13)
TEXT_COLOR = RGBColor(0x33, 0x33, 0x33)
SUBTLE = RGBColor(0x66, 0x66, 0x66)
```

### CJK Font Setup

```python
def set_run_font(run, font_name="PingFang SC", size=Pt(11), color=TEXT_COLOR, bold=False):
    """Set font for a run, with CJK fallback."""
    run.font.name = font_name
    run.font.size = size
    run.font.color.rgb = color
    run.bold = bold
    # Set East Asian font (critical for CJK rendering)
    r = run._element
    rPr = r.get_or_add_rPr()
    rFonts = rPr.get_or_add_rFonts()
    rFonts.set(qn("w:eastAsia"), font_name)
```

### Cover Page

```python
# Add spacing before title
for _ in range(6):
    doc.add_paragraph()

title_para = doc.add_paragraph()
title_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = title_para.add_run("文档标题")
set_run_font(run, size=Pt(32), color=ACCENT, bold=True)

subtitle_para = doc.add_paragraph()
subtitle_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = subtitle_para.add_run("副标题 — 作者名")
set_run_font(run, size=Pt(14), color=SUBTLE)

doc.add_page_break()
```

### TOC (Auto-refresh Field)

```python
from docx.oxml import OxmlElement

def add_toc(doc):
    """Insert TOC field — updates on open in Word (right-click → Update Field)."""
    para = doc.add_paragraph()
    run = para.add_run()
    fldChar1 = OxmlElement("w:fldChar")
    fldChar1.set(qn("w:fldCharType"), "begin")
    run._r.append(fldChar1)

    run2 = para.add_run()
    instrText = OxmlElement("w:instrText")
    instrText.set(qn("xml:space"), "preserve")
    instrText.text = ' TOC \\o "1-3" \\h \\z \\u '
    run2._r.append(instrText)

    run3 = para.add_run()
    fldChar2 = OxmlElement("w:fldChar")
    fldChar2.set(qn("w:fldCharType"), "end")
    run3._r.append(fldChar2)

    doc.add_page_break()

add_toc(doc)
```

### Headings & Paragraphs

```python
def add_heading_styled(doc, text, level=1):
    heading = doc.add_heading(text, level=level)
    for run in heading.runs:
        set_run_font(run, size=Pt(22 if level == 1 else 16),
                     color=ACCENT, bold=True)
    return heading

def add_body(doc, text):
    para = doc.add_paragraph()
    para.paragraph_format.space_after = Pt(6)
    para.paragraph_format.line_spacing = Pt(20)
    run = para.add_run(text)
    set_run_font(run)
    return para

add_heading_styled(doc, "一、概述", level=1)
add_body(doc, "这是正文段落，支持中英文混排。reportlab 和 python-docx 都能处理 CJK 字符。")
```

### Code Blocks

```python
def add_code_block(doc, code_text):
    para = doc.add_paragraph()
    para.paragraph_format.space_before = Pt(6)
    para.paragraph_format.space_after = Pt(6)
    run = para.add_run(code_text)
    run.font.name = "Menlo"
    run.font.size = Pt(9)
    run.font.color.rgb = RGBColor(0x24, 0x29, 0x2E)
    # Light gray background via shading
    shading = OxmlElement("w:shd")
    shading.set(qn("w:fill"), "F5F5F5")
    shading.set(qn("w:val"), "clear")
    run._r.get_or_add_rPr().append(shading)

add_code_block(doc, "def hello():\n    print('world')")
```

### Tables

```python
data = [["公司", "营收", "净利"],
        ["公司A", "100亿", "20亿"],
        ["公司B", "80亿", "15亿"]]

table = doc.add_table(rows=len(data), cols=len(data[0]), style="Table Grid")
table.alignment = WD_TABLE_ALIGNMENT.CENTER

for i, row in enumerate(data):
    for j, cell_text in enumerate(row):
        cell = table.cell(i, j)
        cell.text = ""
        run = cell.paragraphs[0].add_run(cell_text)
        if i == 0:  # header row
            set_run_font(run, size=Pt(10), color=RGBColor(0xFF, 0xFF, 0xFF), bold=True)
            shading = OxmlElement("w:shd")
            shading.set(qn("w:fill"), "8B4513")
            shading.set(qn("w:val"), "clear")
            cell._tc.get_or_add_tcPr().append(shading)
        else:
            set_run_font(run, size=Pt(10))
```

### Images (Local + Remote URL)

```python
def add_image(doc, src, width=Inches(5.5)):
    """Add image from local path or URL."""
    if src.startswith("http"):
        resp = requests.get(src, timeout=15)
        tmp_path = f"/tmp/docx_img_{hash(src)}.png"
        with open(tmp_path, "wb") as f:
            f.write(resp.content)
        src = tmp_path
    if os.path.exists(src):
        doc.add_picture(src, width=width)
        last_para = doc.paragraphs[-1]
        last_para.alignment = WD_ALIGN_PARAGRAPH.CENTER

add_image(doc, "chart.png")
```

### Watermark

```python
def add_watermark(doc, text="CONFIDENTIAL"):
    """Add diagonal text watermark to all sections."""
    for section in doc.sections:
        header = section.header
        para = header.paragraphs[0] if header.paragraphs else header.add_paragraph()
        para.alignment = WD_ALIGN_PARAGRAPH.CENTER
        run = para.add_run(text)
        run.font.size = Pt(48)
        run.font.color.rgb = RGBColor(0xDD, 0xDD, 0xDD)

# For proper diagonal watermark, use WordprocessingML shape in header
# (simplified version above; full implementation uses VML shape)
```

### Build Final Document

```python
doc.save("output.docx")
```

## Options

| Option | Default | Description |
|--------|---------|-------------|
| `--input` | (required) | Markdown file path |
| `--output` | `output.docx` | Output DOCX path |
| `--title` | From H1 | Cover page title |
| `--subtitle` | | Subtitle |
| `--author` | | Author name |
| `--theme` | `warm-academic` | Color theme |
| `--watermark` | | Watermark text |
| `--cover` | `true` | Generate cover page |
| `--toc` | `true` | Generate table of contents |

## Themes (11 themes)

**Light:** `warm-academic`, `nord-frost`, `github-light`, `solarized-light`, `paper-classic`, `ocean-breeze`, `tufte`, `classic-thesis`
**CJK-optimized:** `chinese-red`, `ink-wash`, `elegant-book`
**Dark:** `monokai-warm`, `dracula-soft`

## VisionClaw Integration

When used with the document-illustrator sub-skill, images generated via VisionClaw's `gemini` tool can be embedded directly into the DOCX. The agent should:

1. Generate illustrations first (using `gemini` tool with `output_modality="image"`)
2. Insert image references into the Markdown
3. Convert to DOCX with embedded images using `document.add_picture()`
