├── .gitignore ├── Dockerfile ├── Readme.md ├── action.yml ├── build.py └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | input/ 2 | output/ 3 | *.odt 4 | *.pdf 5 | *.md~ 6 | __pycache__/ 7 | *.log 8 | .idea/ 9 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.10-slim 2 | 3 | RUN apt-get update && apt-get install -y --no-install-recommends \ 4 | pandoc \ 5 | libreoffice \ 6 | ghostscript \ 7 | && apt-get clean \ 8 | && rm -rf /var/lib/apt/lists/* 9 | 10 | COPY requirements.txt /tmp/requirements.txt 11 | 12 | RUN pip install --no-cache-dir -r /tmp/requirements.txt 13 | 14 | WORKDIR /app 15 | 16 | COPY . /app 17 | 18 | ENTRYPOINT ["python3", "build.py"] 19 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Docs automation 2 | 3 | Плагин Github Actions для автоматической генерации документов по кускам. Пока реализуется под конкретную задачу (формирование отчёта ВКР по кускам). 4 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: "light-hat/docs-automation" 2 | description: "Автоматизирует формирование документов по частям." 3 | branding: 4 | icon: "book" 5 | color: "yellow" 6 | inputs: 7 | message: 8 | description: "Message to print" 9 | required: true 10 | default: "Hello, World!" 11 | outputs: 12 | result: 13 | description: "The result of the Action" 14 | runs: 15 | using: "composite" 16 | steps: 17 | - name: Print message 18 | run: echo "${{ inputs.message }}" 19 | shell: bash 20 | - name: Set output 21 | run: echo "result=Done" >> $GITHUB_ENV 22 | shell: bash 23 | -------------------------------------------------------------------------------- /build.py: -------------------------------------------------------------------------------- 1 | """ 2 | Скрипт для сборки финального документа. 3 | """ 4 | 5 | import os 6 | import subprocess 7 | import yaml 8 | 9 | 10 | def combine_markdown_to_odt(md_files, output_file, template): 11 | combined_md = "combined.md" 12 | with open(combined_md, "w") as outfile: 13 | for fname in md_files: 14 | with open(fname) as infile: 15 | outfile.write(infile.read() + "\n\n") 16 | 17 | subprocess.run([ 18 | "pandoc", combined_md, "-o", output_file, "--reference-doc", template, "--toc" 19 | ]) 20 | os.remove(combined_md) 21 | 22 | def build_document(structure_file, output_dir, template_file): 23 | with open(structure_file, "r") as file: 24 | structure = yaml.safe_load(file) 25 | 26 | output_files = [] 27 | for part in structure["parts"]: 28 | if part["type"] == "text": 29 | md_files = part["files"] 30 | odt_file = os.path.join(output_dir, f"{part['name']}.odt") 31 | combine_markdown_to_odt(md_files, odt_file, template_file) 32 | output_files.append(odt_file) 33 | elif part["type"] == "cover": 34 | output_files.append(part["file"]) 35 | elif part["type"] == "image": 36 | output_files.append(part["file"]) 37 | 38 | # Объединяем части 39 | final_odt = os.path.join(output_dir, "final_document.odt") 40 | subprocess.run(["libreoffice", "--headless", "--convert-to", "odt"] + output_files + [final_odt]) 41 | 42 | # Конвертируем ODT в PDF 43 | final_pdf = os.path.join(output_dir, "final_document.pdf") 44 | subprocess.run(["libreoffice", "--headless", "--convert-to", "pdf", final_odt]) 45 | 46 | print(f"Documents generated: {final_odt}, {final_pdf}") 47 | 48 | if __name__ == "__main__": 49 | STRUCTURE_FILE = "structure.yml" 50 | OUTPUT_DIR = "/output" 51 | TEMPLATE_FILE = "template.ott" 52 | 53 | os.makedirs(OUTPUT_DIR, exist_ok=True) 54 | 55 | build_document(STRUCTURE_FILE, OUTPUT_DIR, TEMPLATE_FILE) 56 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pyuno 2 | pyyaml 3 | --------------------------------------------------------------------------------