Conversion de ficheros a docx mediante script en python
This commit is contained in:
parent
ba5994e4d4
commit
cd610cf798
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,136 @@
|
||||||
|
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
Convierte Markdown a PDF y DOCX por bloques, concatenando bloque{i}/tema*.md.
|
||||||
|
|
||||||
|
Requisitos:
|
||||||
|
- Python 3.9+
|
||||||
|
- Pandoc instalado (en PATH). Comprobar con: pandoc --version
|
||||||
|
- Para PDF (weasyprint): pip install weasyprint y librerías gráficas según SO.
|
||||||
|
- Opcional: plantilla DOCX para estilos (--reference-doc=plantilla.docx)
|
||||||
|
|
||||||
|
Uso:
|
||||||
|
python convert_md.py --bloques 1 2 3 4 --css estilos.css --ref plantilla.docx --outdir-pdf pdfs --outdir-docx docx
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import shutil
|
||||||
|
from datetime import datetime
|
||||||
|
from pathlib import Path
|
||||||
|
from glob import glob
|
||||||
|
|
||||||
|
def check_cmd_exists(cmd: str) -> bool:
|
||||||
|
return shutil.which(cmd) is not None
|
||||||
|
|
||||||
|
def run_cmd(cmd_list):
|
||||||
|
try:
|
||||||
|
subprocess.run(cmd_list, check=True)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"❌ Error ejecutando: {' '.join(cmd_list)}\n{e}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def build_pandoc_common_args(input_md: Path, title: str):
|
||||||
|
return [
|
||||||
|
"pandoc", str(input_md),
|
||||||
|
"--from", "markdown",
|
||||||
|
"--toc",
|
||||||
|
"--metadata", f"title={title}",
|
||||||
|
]
|
||||||
|
|
||||||
|
def convert_to_pdf(input_md: Path, output_pdf: Path, css: str | None):
|
||||||
|
args = build_pandoc_common_args(input_md, title=output_pdf.stem)
|
||||||
|
args += ["-o", str(output_pdf), "--pdf-engine=weasyprint"]
|
||||||
|
if css:
|
||||||
|
args += ["--css", css]
|
||||||
|
# Embebe recursos (imágenes, etc.) y usa rutas relativas al md
|
||||||
|
args += ["--embed-resources", "--resource-path", f".;{input_md.parent}"]
|
||||||
|
run_cmd(args)
|
||||||
|
|
||||||
|
def convert_to_docx(input_md: Path, output_docx: Path, ref_doc: str | None):
|
||||||
|
args = build_pandoc_common_args(input_md, title=output_docx.stem)
|
||||||
|
args += ["--to", "docx", "-o", str(output_docx)]
|
||||||
|
if ref_doc:
|
||||||
|
args += ["--reference-doc", ref_doc]
|
||||||
|
args += ["--embed-resources", "--resource-path", f".;{input_md.parent}"]
|
||||||
|
run_cmd(args)
|
||||||
|
|
||||||
|
def concat_markdown(block_dir: Path, out_md: Path) -> int:
|
||||||
|
temas = sorted(glob(str(block_dir / "tema*.md")))
|
||||||
|
if not temas:
|
||||||
|
return 0
|
||||||
|
with out_md.open("w", encoding="utf-8") as f_out:
|
||||||
|
for md in temas:
|
||||||
|
with open(md, "r", encoding="utf-8") as f_in:
|
||||||
|
f_out.write(f_in.read().rstrip() + "\n\n")
|
||||||
|
return len(temas)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
hoy = datetime.now().strftime("_%Y%m%d")
|
||||||
|
# parser = argparse.ArgumentParser(description="Convertir Markdown a PDF y DOCX por bloques.")
|
||||||
|
# parser.add_argument("--bloques", nargs="+", type=int, required=True,
|
||||||
|
# help="Lista de números de bloque, ej.: 1 2 3 4")
|
||||||
|
# parser.add_argument("--css", type=str, default=None, help="CSS para PDF (WeasyPrint)")
|
||||||
|
# parser.add_argument("--ref", type=str, default=None, help="Documento de referencia DOCX (plantilla.docx)")
|
||||||
|
# parser.add_argument("--outdir-pdf", type=str, default="pdfs", help="Carpeta salida PDF")
|
||||||
|
# parser.add_argument("--outdir-pdf", type=str, default="pdfs", help="Carpeta salida PDF")
|
||||||
|
# parser.add_argument("--outdir-docx", type=str, default="docx", help="Carpeta salida DOCX")
|
||||||
|
# parser.add_argument("--keep-md", action="store_true", help="Mantener los .md concatenados")
|
||||||
|
# args = parser.parse_args()
|
||||||
|
|
||||||
|
# Comprobaciones
|
||||||
|
if not check_cmd_exists("pandoc"):
|
||||||
|
print("❌ No se encontró 'pandoc' en PATH. Instálalo y vuelve a ejecutar.", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# WeasyPrint es opcional, pero si vas a PDF conviene avisar si no está
|
||||||
|
weasy_available = check_cmd_exists("weasyprint")
|
||||||
|
# if args.css and not Path(args.css).exists():
|
||||||
|
# print(f"⚠️ CSS no encontrado: {args.css} (se omitirá en PDF)")
|
||||||
|
|
||||||
|
outdir_pdf = Path("pdfs")
|
||||||
|
outdir_docx = Path("docx")
|
||||||
|
fichero_plantilla = Path("plantilla.docx")
|
||||||
|
outdir_pdf.mkdir(parents=True, exist_ok=True)
|
||||||
|
outdir_docx.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
for i in 1, 2, 3, 4:
|
||||||
|
block_dir = Path(f"bloque{i}")
|
||||||
|
if not block_dir.exists():
|
||||||
|
print(f"⚠️ No existe el directorio {block_dir} — se omite el bloque {i}.")
|
||||||
|
continue
|
||||||
|
|
||||||
|
out_md = Path(f"bloque{i}-completo{hoy}.md")
|
||||||
|
count = concat_markdown(block_dir, out_md)
|
||||||
|
if count == 0:
|
||||||
|
print(f"⚠️ No hay archivos tema*.md en {block_dir} — se omite este bloque.")
|
||||||
|
continue
|
||||||
|
print(f"✔ Generado {out_md} ({count} temas concatenados)")
|
||||||
|
|
||||||
|
title = f"Bloque {i} - Actualizado el {hoy}"
|
||||||
|
|
||||||
|
# DOCX
|
||||||
|
out_docx = outdir_docx / f"bloque{i}.docx"
|
||||||
|
convert_to_docx(out_md, out_docx, str(fichero_plantilla) if fichero_plantilla.exists() else None)
|
||||||
|
print(f"📝 DOCX generado: {out_docx}")
|
||||||
|
|
||||||
|
# PDF
|
||||||
|
out_pdf = outdir_pdf / f"bloque{i}.pdf"
|
||||||
|
if weasy_available:
|
||||||
|
css = args.css if args.css and Path(args.css).exists() else None
|
||||||
|
convert_to_pdf(out_md, out_pdf, css)
|
||||||
|
print(f"📄 PDF generado: {out_pdf}")
|
||||||
|
else:
|
||||||
|
print("⚠️ WeasyPrint no está disponible. Instálalo para generar PDF, o usa otra ruta (MiKTeX).")
|
||||||
|
|
||||||
|
# Limpieza
|
||||||
|
try:
|
||||||
|
out_md.unlink()
|
||||||
|
except Exception:
|
||||||
|
pass # Si quieres mantenerlos, usa --keep-md
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Binary file not shown.
Binary file not shown.
11
convertir-bloques-completos.sh → scriptsLinux/convertir-bloques-completos.sh
Executable file → Normal file
11
convertir-bloques-completos.sh → scriptsLinux/convertir-bloques-completos.sh
Executable file → Normal file
|
|
@ -1,10 +1,13 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Script para concatenar archivos tema*.md en bloques completos y generar PDFs
|
||||||
|
# La idea es crear el temario en markdown, que es facil de editar, y luego
|
||||||
|
# generar un PDF con formato adecuado, y poder estudiar en papel.
|
||||||
HOY=$(date +%Y%m%d)
|
HOY=$(date +%Y%m%d)
|
||||||
|
|
||||||
for i in 1 2 3 4; do
|
for i in 1 2 3 4; do
|
||||||
# Buscar archivos tema*.md
|
# Buscar archivos tema*.md
|
||||||
FILES=(bloque$i/tema*.md)
|
FILES=(../bloque$i/tema*.md)
|
||||||
|
|
||||||
# Comprobar si existen
|
# Comprobar si existen
|
||||||
if [ ! -e "${FILES[0]}" ]; then
|
if [ ! -e "${FILES[0]}" ]; then
|
||||||
|
|
@ -13,14 +16,14 @@ for i in 1 2 3 4; do
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Concatenar
|
# Concatenar
|
||||||
OUT_MD="bloque${i}-completo${HOY}.md"
|
OUT_MD="../bloque${i}-completo${HOY}.md"
|
||||||
cat bloque$i/tema*.md > "$OUT_MD"
|
cat ../bloque$i/tema*.md > "$OUT_MD"
|
||||||
|
|
||||||
echo "✔ Generado $OUT_MD"
|
echo "✔ Generado $OUT_MD"
|
||||||
|
|
||||||
# Crear PDF
|
# Crear PDF
|
||||||
pandoc "$OUT_MD" \
|
pandoc "$OUT_MD" \
|
||||||
-o "pdfs/bloque${i}_${HOY}.pdf" \
|
-o "../pdfs/bloque${i}_${HOY}.pdf" \
|
||||||
--pdf-engine=weasyprint \
|
--pdf-engine=weasyprint \
|
||||||
--css=estilos.css \
|
--css=estilos.css \
|
||||||
--toc \
|
--toc \
|
||||||
Loading…
Reference in New Issue