""" Convert file Markdown (.md) sang Word (.docx) / HTML / PDF bang pandoc. CACH DUNG: chi can BAM CHAY (Run trong VSCode/PyCharm, hoac double-click). Khong can go lenh / khong can nhap args. Chinh cau hinh o khoi CONFIG ben duoi. CAI 1 LAN (neu chua co): python -m pip install pypandoc_binary """ # ===================================================================== # CONFIG -- SUA TRUC TIEP O DAY ROI BAM CHAY # ===================================================================== # File can convert. Co the la: # - 1 ten file: "methodology_rewrite.md" # - nhieu file: ["methodology_rewrite.md", "bai2.md"] # - tat ca file .md: "ALL" INPUT = "methodology_rewrite.md" # Dinh dang dau ra: "docx" | "html" | "pdf" OUTPUT_FORMAT = "docx" # Ten file dau ra. De None thi tu dat trung ten file goc (chi dung khi INPUT la 1 file). OUTPUT_NAME = None # GOP NHIEU FILE THANH 1 BAO CAO: # - De COMBINE = [] (rong) -> dung che do INPUT o tren (convert tung file rieng). # - Liet ke file theo dung thu tu -> gop thanh 1 file COMBINE_OUTPUT duy nhat. COMBINE = ["report_front.md", "report_part1.md", "methodology_rewrite.md", "report_part4_5.md"] COMBINE_OUTPUT = "report.docx" # ===================================================================== # (Khong can sua tu day tro xuong) # ===================================================================== import sys from pathlib import Path HERE = Path(__file__).resolve().parent def ensure_pypandoc(): try: import pypandoc # noqa: F401 return except ImportError: print("[!] Chua co pypandoc. Dang cai 'pypandoc_binary' (kem san pandoc)...") import subprocess subprocess.check_call( [sys.executable, "-m", "pip", "install", "--quiet", "pypandoc_binary"] ) print("[+] Cai xong.") def convert_one(md_path: Path, to_fmt: str, out_path: Path | None) -> Path: import pypandoc if not md_path.exists(): raise FileNotFoundError(f"Khong tim thay file: {md_path}") if out_path is None: out_path = md_path.with_suffix("." + to_fmt) # --resource-path: de pandoc tim duoc anh (figures/...) du chay tu thu muc nao extra_args = ["--toc", "--toc-depth=3", "--resource-path", str(md_path.parent)] if to_fmt == "html": extra_args += ["--standalone", "--mathjax", "--embed-resources"] elif to_fmt == "pdf": extra_args += ["-V", "geometry:margin=2.5cm"] pypandoc.convert_file( str(md_path), to_fmt, outputfile=str(out_path), extra_args=extra_args ) return out_path def combine_files(names, out_name) -> Path: """Gop nhieu file .md (theo thu tu) thanh 1 file dau ra duy nhat.""" import pypandoc parts = [] for n in names: p = (HERE / n) if not Path(n).is_absolute() else Path(n) if not p.exists(): raise FileNotFoundError(f"Khong tim thay file: {p}") parts.append(p.read_text(encoding="utf-8")) text = "\n\n".join(parts) to_fmt = Path(out_name).suffix.lstrip(".") or "docx" out_path = (HERE / out_name) if not Path(out_name).is_absolute() else Path(out_name) extra_args = ["--toc", "--toc-depth=3", "--resource-path", str(HERE)] if to_fmt == "html": extra_args += ["--standalone", "--mathjax", "--embed-resources"] pypandoc.convert_text(text, to_fmt, format="markdown", outputfile=str(out_path), extra_args=extra_args) return out_path def resolve_inputs(inp) -> list[Path]: if isinstance(inp, str) and inp.upper() == "ALL": return sorted(HERE.glob("*.md")) if isinstance(inp, (list, tuple)): return [(HERE / x) if not Path(x).is_absolute() else Path(x) for x in inp] p = Path(inp) return [p if p.is_absolute() else HERE / p] def main(): ensure_pypandoc() # Che do gop nhieu file thanh 1 bao cao (uu tien neu COMBINE khong rong) if COMBINE: try: out = combine_files(COMBINE, COMBINE_OUTPUT) print(f"[+] Gop {len(COMBINE)} file -> {out.name}") except Exception as e: # noqa: BLE001 print(f"[x] Loi khi gop: {e}") return md_files = resolve_inputs(INPUT) if not md_files: print("[!] Khong tim thay file .md nao de convert.") return many = len(md_files) > 1 for md in md_files: out = None if OUTPUT_NAME and not many: out = Path(OUTPUT_NAME) if not out.is_absolute(): out = HERE / out try: result = convert_one(md, OUTPUT_FORMAT, out) print(f"[+] {md.name} -> {result.name}") except Exception as e: # noqa: BLE001 print(f"[x] Loi voi {md.name}: {e}") if OUTPUT_FORMAT == "pdf": print(" -> PDF can mot LaTeX engine (MiKTeX/TeX Live). " "Thu doi OUTPUT_FORMAT='html' roi in PDF tu trinh duyet.") if __name__ == "__main__": main() # Giu cua so terminal mo khi double-click tren Windows try: if sys.stdin and sys.stdin.isatty(): input("\nXong. Nhan Enter de dong...") except Exception: pass