report-maker 0.2.2
A tool to convert Markdown documents into a single .docx report with proper formatting
License: BSD 2-clause license
Requires Python: >=3.12

# Report Maker
This Python package provides tools for compiling multiple Markdown sources and Python source files
together into a single `.docx` report file while also adding extra information like title page, ToC, and appendices
while respecting Governmental Standards (aka GOSTs).

This project used to be term 4 educational practice
in the [GUAP] university but outgrew that.
The original code, as well as the term project report, can be seen [here][term project].


## Features
 - [x] Converts Markdown pages, including:
     - [x] Support for extended Markdown syntax
     - [ ] Configurable Markdown extensions list
     - [ ] Full support of fancy code blocks, like syntax highlight or math expressions
     - [x] Automatically numbered chapters
     - [x] Automatically numbered and labeled pictures
     - [x] Automatically numbered appendix
 - [x] Inserts "infrastructural" pages, including:
   - [x] Templated document, like
     (must be provided by the active template)
   - [x] Plain document, like Table of Contents
     (must be provided by the active template) 
   - [x] Source code in the document appendix
   - [x] Source code license file in the document appendix
 - [x] Full external templates support
 - [ ] *(Planned only)* Full external extensions support

## Usage
1. Install via `pip`:
   ```
   pip install report-maker[all]
   ```
2. Install any of the template plugins:
   * For GOTS-7.32, install as:
     ```
     pip install report-maker-template-gost-7.32
     ```
3. Add `report-composer.conf` config ([see below](#composer-config))
4. Run `report-composer` (or `python -m report_composer`)

## Documentation
### Feature flags
The project comes with a number of feature flags,
some of them (especially math-related) are quite heavy:

`math`
: Plugins to convert inline math code and math code blocks
  into MS Word math blocks.

`code`
: Plugins to add code blocks highlights and source code formatting

`extras`
: Plugins for extra functionality

`all`
: All possible feature flags

### Command-line Options
**Usage:**
```
report-maker [OPTIONS]
```

**Options:**

`-h|--help`
:   Show help message and exit

`--config|-c CONFIG`
:   Path to the configuration file
    Default value: `report-composer.conf`

`--log-level|-l DEBUG|INFO|WARNING|ERROR|CRITICAL`
:   Logging level for the app
    Default value: `INFO`


### Composer Config
The Report Raker uses the report composer to compose the report.
The latter requires the composer config in [HOCON] format,
usually named `report-composer.conf`

The composer config MUST contain `composer` top-level section.
This section may have the following properties:
* `template` *(string)*: **REQUIRED.**
  ID of the template used.
  See [Templating](#templating).
* `overrides` *(config)*: Optional.
  A config of overrides applied globally to the template styles loader,
  i.e. font names or intent size.
* `build_dir` *(relative path)*: Optional, default: `build/`.
  Directory used to store temporary files during document build.
  May contain caches for faster project re-building.
* `target` *(relative path)*: Optional, default: `report.docx`.
  Path to the resulting document,
  relative to the current working directory.
* `parts` *(list)*: **REQUIRED.**
  List of parts to compose.
  All parts are executed in order.
  See below.

Composer Parts
:   All composer parts MUST define
    `name` (unique string) and `type`.
    Other properties vary for different part types.

Markdown Converter (`type: markdown`)
:   Module which (optionally) discovers and converts Markdown files.
    Supported parameters:

* `root` *(relative path)*: **REQUIRED.**
  Root directory for the module, relative to the working directory.
* `discover` *(boolean)*: **REQUIRED.**
  Defines the behaviour of this module.
  + With `discover: true`, automatically includes all files matching a pattern.
    Patterns may be overridden via `patterns` (list of strings) option.
    By default, recursively includes all Markdown (`*.md`, `*.markdown`) files.
    Files are sorted alphabetically.
  + With `discover: false`, module includes only files listed in the `files` option.
    Files are ordered as listed.
* `files` *(list)*: A list of files to include.
  Each file must have either `file` or `glob`:
  + `file` *(relative path)*: Single file relative to the `root`
  + `glob` *(relative path pattern)*: Pattern of files relative toe the `root`
  + `is_main_body` *(boolean)*: Optional, default: `false`.
    May be set to `true` for main chapters, affects formatting.

Source Code Converter (`type: source-code`)
:   Behaves similarly to the Markdown Converter,
    but discovers and inserts source code files.

* `root` *(relative path)*: **REQUIRED.**
  Root directory for the module, relative to the working directory.
* `discover` *(boolean)*: **REQUIRED.**
  Defines the behaviour of this module.
  + With `discover: true`, automatically includes all files matching a pattern.
    Patterns may be overridden via `patterns` (list of strings) option.
    By default, recursively includes all Python source code (`*.py`, `*.pyi`) files.
    Files are sorted alphabetically.
  + With `discover: false`, module includes only files listed in the `files` option.
    Files are ordered as listed.
* `files` *(list)*: A list of files to include.
  Each file must have either `file` or `glob`:
  + `file` *(relative path)*: Single file relative to the `root`
  + `glob` *(relative path pattern)*: Pattern of files relative toe the `root`
* `style_profile` *(string)*: Optional, a name for the Pygments profile
* `split_code_blocks` *(boolean)*: Optional, default: `true`.
  When set, code blocks are split into paragraphs by empty lines.

Static File (`type: document`)
:   Inserts the file from `document_path` *(relative path)*.
    Styles are merged, otherwise unchanged.

Static Template (`type: from-template`)
:   Inserts the static file `document_path` *(path from the template root)* from the active template.
    Behaves similarly to Static File.

Dynamic Template (`type: template`)
:   Inserts the dynamic template `template` *(path from the template root)* from the active template.
    Substitutes values listed in the `attributes` *(config section)*.
    Otherwise, behaves like Static Template.
    Refer to the template's documentation for the list of attributes required.

License Reference (`type: license`)
:   Inserts the license text either from a file or from templates.
    Supported parameters:

* `license_kind`: `custom` or `built-in`
  + With `license_kind: custom`, no dynamic logic is used
  + With `license_kind: built-in`, license may be rendered by the [license][pypi:license] package
  + Regardless of choice, `license_name` and `license_file` options are respected.
* `license_id` *(string)*: Required if `built-in`, license identifier from the license library
* `license_name` *(string)*: Required if `custom`, license human-readable name
* `license_file` *(string)*: Required if `custom`, a license file to include
* `options` *(config section)*: Options for rendering license text, like author's `name` or `email`

Appendix Wrapper (`type: appendix`)
:   Wraps the module defined in `appendix` as an appendix.
    Appendices are numbered by default,
    use `numbered: false` to disable.
    Otherwise, the module is unaffected.


#### Example configuration
Example configuration for the [GOST-7.32] template
```hocon
paths:
{
    build_dir: build
    data_dir: docs
    target_dir: out
    source_code: src
}

composer:
{
    template: "gost-7.32"
    build_dir: ${paths.build_dir}
    target: ${paths.target_dir}/report.docx
    
    parts:
    [
        {
            name: title
            type: document
            document_path: ${paths.data_dir}/src/front-page.docx
        },
        {
            name: toc
            type: from-template
            document_path: "toc.docx"
        },
        {
            name: body
            type: markdown
            discover: false
            root: ${paths.data_dir}/report
            files:
            [
                { file = "intro.md",        is_main_body = false },
                { glob = "chapter-*.md",    is_main_body = true  },
                { file = "conclusion.md",   is_main_body = false },
                { file = "sources.md",      is_main_body = false },
            ]
        },
        {
            name: source-code
            type: appendix
            appendix:
            {
                type: source-code
                discover: true
                root: ${paths.source_code}
            }
        },
        {
            name: license
            type: appendix
            appendix:
            {
                type: license
                license_kind: built-in
                license_id: "BSD-2-Clause"
                license_file: "License.txt"
                
                font_size_override: 8
                options:
                {
                    name: "Peter Zaitcev"
                    email: "zaitcev.po@gmai.com"
                }
            }
        },
    ]
}
```

### Templating
Report Maker requires an installed template extension to run.
A list of all official extensions can be found here:
https://gitlab.com/Hares-Lab/report-maker/templates

Third-parties may also provide their own extensions.


## Licensing
*see: [LICENSE.txt](./LICENSE.txt)*

[BSD-2 License].
Copyright (c) Peter Zaitcev, 2025.

<!-- Links -->
[GUAP]: https://guap.ru
[Term Project]: https://gitlab.com/Hares-Lab/educational/t4-educational-practice
[HOCON]: https://github.com/lightbend/config/blob/main/HOCON.md#hocon-human-optimized-config-object-notation
[GOST-7.32]: https://gitlab.com/Hares-Lab/report-maker/templates/gost-7.32
[pypi:license]: https://pypi.org/project/license/
[BSD-2 License]: https://opensource.org/license/bsd-2-clause