Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Docker Image CI

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:

build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Build the Docker image
run: docker build . --file Dockerfile --tag my-image-name:$(date +%s)
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,19 @@ In addition to the packages specified in the table above, the following packages
- `bazelisk` / `bazel`

See [Dockerfile](Dockerfile) for the full details of installed packages.

## Legal document generator module

This repository includes a simple example module located in `legal_module/` that demonstrates how to generate Traditional Chinese legal filings using the `python-docx` package. The module exposes a `create_filing` function that accepts case information and outputs a formatted Word document. When `docx2pdf` is available the file can also be exported to PDF. Generated documents use **2.5 cm margins**, **1.5 line spacing**, and include an optional **附件** section for supporting materials.

Example usage:

```bash
python3 -m legal_module.example
```

This requires the optional dependencies **python-docx** and **docx2pdf** for PDF export. Install them with:

```bash
pip install python-docx docx2pdf
```
Empty file added legal_module/__init__.py
Empty file.
21 changes: 21 additions & 0 deletions legal_module/example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from .filing import create_filing

sample_case = {
'case_number': '臺北地方法院114年度訴字第1234號',
'parties': '原告:李灃祐 被告:新鑫公司',
'court': '臺灣臺北地方法院',
'claims': '請求確認本票債權不存在,並請求返還不當得利新台幣1,000,000元。',
'facts': '原告與被告簽署車輛分期契約,惟車輛自始未交付,卻遭告提出票據裁定……',
'laws': ['民法第184條', '票據法第17條', '最高法院111年度台上字第3208號判決'],
'evidence': [
{'id': '乙1', 'summary': 'LINE對話紀錄,顯示告知車輛尚未交付'},
{'id': '乙2', 'summary': '川立公司匯款憑證,顯示資金流向'}
],
'attachments': [
{'id': '附件一', 'description': '車輛分期契約影本'},
]
}

if __name__ == '__main__':
create_filing(sample_case, '法律文書_起訴狀.docx', pdf_path='法律文書_起訴狀.pdf')
print('Documents generated: 法律文書_起訴狀.docx, 法律文書_起訴狀.pdf')
116 changes: 116 additions & 0 deletions legal_module/filing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
from typing import Any, Dict, Optional
from pathlib import Path
import tempfile

try:
from docx import Document
from docx.shared import Pt, Cm
except ImportError: # pragma: no cover - docx may not be installed
Document = None
Pt = None

class LegalDocumentGenerator:
"""Generate legal filings in Traditional Chinese."""

def __init__(self, case_info: Dict[str, Any]):
self.case_info = case_info
if Document is None:
raise RuntimeError(
"python-docx is required to generate documents. Please install it via 'pip install python-docx'."
)
self.doc = Document()
style = self.doc.styles["Normal"]
font = style.font
font.name = "標楷體"
font.size = Pt(16)
style.paragraph_format.line_spacing = Pt(24) # 1.5 line spacing

for section in self.doc.sections:
section.top_margin = Cm(2.5)
section.bottom_margin = Cm(2.5)
section.left_margin = Cm(2.5)
section.right_margin = Cm(2.5)

def build(self) -> None:
self.doc.add_heading(self.case_info.get('title', '起訴狀'), level=1)
self._add_basic_info()
self._add_claims()
self._add_facts()
self._add_laws()
self._add_evidence()
self._add_attachments()

def save(self, filepath: str) -> None:
self.doc.save(filepath)

def save_pdf(self, filepath: str) -> None:
"""Save the generated document as a PDF using docx2pdf if available."""
try:
from docx2pdf import convert
except ImportError as exc: # pragma: no cover - optional dependency
raise RuntimeError(
"docx2pdf is required for PDF export. Install it via 'pip install docx2pdf'."
) from exc

with tempfile.TemporaryDirectory() as tmpdir:
docx_path = Path(tmpdir) / "temp.docx"
self.doc.save(docx_path)
convert(str(docx_path), filepath)

# Internal helpers
def _add_basic_info(self) -> None:
self.doc.add_paragraph(f"案號:{self.case_info.get('case_number', '')}")
self.doc.add_paragraph(f"當事人:{self.case_info.get('parties', '')}")
self.doc.add_paragraph(f"法院:{self.case_info.get('court', '')}")

def _add_claims(self) -> None:
self.doc.add_paragraph("壹、訴之聲明")
self.doc.add_paragraph(self.case_info.get('claims', ''))

def _add_facts(self) -> None:
self.doc.add_paragraph("貳、事實與理由")
self.doc.add_paragraph(self.case_info.get('facts', ''))

def _add_laws(self) -> None:
self.doc.add_paragraph("參、法律依據")
for law in self.case_info.get('laws', []):
self.doc.add_paragraph(f"• {law}")

def _add_evidence(self) -> None:
self.doc.add_paragraph("肆、證據目錄")
for ev in self.case_info.get('evidence', []):
self.doc.add_paragraph(f"【{ev['id']}】{ev['summary']}")

def _add_attachments(self) -> None:
attachments = self.case_info.get("attachments")
if not attachments:
return
self.doc.add_paragraph("伍、附件")
for att in attachments:
desc = att.get("description", "")
att_id = att.get("id", "")
self.doc.add_paragraph(f"【{att_id}】{desc}")


def create_filing(
case_info: Dict[str, Any],
output_path: str,
pdf_path: Optional[str] = None,
) -> None:
"""Helper function to quickly generate a filing document.

Parameters
----------
case_info : Dict[str, Any]
Information about the case.
output_path : str
Location to write the DOCX file.
pdf_path : Optional[str]
If provided, also export the document to this PDF path.
"""
generator = LegalDocumentGenerator(case_info)
generator.build()
generator.save(output_path)
if pdf_path:
generator.save_pdf(pdf_path)

2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
python-docx
docx2pdf