Metadata-Version: 2.5
Name: markweave
Version: 0.7.2
Summary: Secure Markdown-to-DOCX and PDF conversion service and HTTP CLI
Project-URL: Documentation, https://github.com/Guillaume-Lombardo/simple-md-to-docx-converter/blob/main/docs/python-distribution.md
Project-URL: Issues, https://github.com/Guillaume-Lombardo/simple-md-to-docx-converter/issues
Project-URL: Repository, https://github.com/Guillaume-Lombardo/simple-md-to-docx-converter
Project-URL: Source, https://github.com/Guillaume-Lombardo/simple-md-to-docx-converter
Project-URL: Support, https://github.com/Guillaume-Lombardo/simple-md-to-docx-converter/discussions
Author-email: Guillaume Lombardo <lombardo.guillaume@gmail.com>
Maintainer-email: Guillaume Lombardo <lombardo.guillaume@gmail.com>
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: cli,conversion,docx,markdown,pdf
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Text Processing :: Markup
Requires-Python: <3.15,>=3.14
Provides-Extra: all
Requires-Dist: alembic<2,>=1.16; extra == 'all'
Requires-Dist: argon2-cffi<26,>=25.1; extra == 'all'
Requires-Dist: boto3<2,>=1.43.82; extra == 'all'
Requires-Dist: cairosvg<3,>=2.8; extra == 'all'
Requires-Dist: fastapi<1,>=0.116; extra == 'all'
Requires-Dist: markdown-it-py<5,>=4; extra == 'all'
Requires-Dist: mdit-py-plugins<0.7,>=0.5; extra == 'all'
Requires-Dist: pillow<13,>=12; extra == 'all'
Requires-Dist: psycopg[binary]<4,>=3.3.4; extra == 'all'
Requires-Dist: pydantic-settings<3,>=2.10; extra == 'all'
Requires-Dist: pypdf<7,>=6.16.2; extra == 'all'
Requires-Dist: python-multipart<1,>=0.0.20; extra == 'all'
Requires-Dist: pyyaml<7,>=6; extra == 'all'
Requires-Dist: sqlalchemy<3,>=2.0; extra == 'all'
Requires-Dist: tinycss2<2,>=1.5; extra == 'all'
Requires-Dist: uvicorn<1,>=0.35; extra == 'all'
Provides-Extra: distributed
Requires-Dist: alembic<2,>=1.16; extra == 'distributed'
Requires-Dist: argon2-cffi<26,>=25.1; extra == 'distributed'
Requires-Dist: boto3<2,>=1.43.82; extra == 'distributed'
Requires-Dist: cairosvg<3,>=2.8; extra == 'distributed'
Requires-Dist: fastapi<1,>=0.116; extra == 'distributed'
Requires-Dist: markdown-it-py<5,>=4; extra == 'distributed'
Requires-Dist: mdit-py-plugins<0.7,>=0.5; extra == 'distributed'
Requires-Dist: pillow<13,>=12; extra == 'distributed'
Requires-Dist: psycopg[binary]<4,>=3.3.4; extra == 'distributed'
Requires-Dist: pydantic-settings<3,>=2.10; extra == 'distributed'
Requires-Dist: pypdf<7,>=6.16.2; extra == 'distributed'
Requires-Dist: python-multipart<1,>=0.0.20; extra == 'distributed'
Requires-Dist: pyyaml<7,>=6; extra == 'distributed'
Requires-Dist: sqlalchemy<3,>=2.0; extra == 'distributed'
Requires-Dist: tinycss2<2,>=1.5; extra == 'distributed'
Requires-Dist: uvicorn<1,>=0.35; extra == 'distributed'
Provides-Extra: kubernetes
Requires-Dist: grpcio<2,>=1.76; extra == 'kubernetes'
Requires-Dist: kubernetes==36.0.3; extra == 'kubernetes'
Requires-Dist: protobuf<7,>=6.33; extra == 'kubernetes'
Provides-Extra: reverse-attempt
Requires-Dist: cairosvg<3,>=2.8; extra == 'reverse-attempt'
Requires-Dist: defusedxml<1,>=0.7; extra == 'reverse-attempt'
Requires-Dist: firecrawl-anydoc==0.2.4; extra == 'reverse-attempt'
Requires-Dist: pillow<13,>=12; extra == 'reverse-attempt'
Requires-Dist: tinycss2<2,>=1.5; extra == 'reverse-attempt'
Provides-Extra: server
Requires-Dist: alembic<2,>=1.16; extra == 'server'
Requires-Dist: argon2-cffi<26,>=25.1; extra == 'server'
Requires-Dist: cairosvg<3,>=2.8; extra == 'server'
Requires-Dist: fastapi<1,>=0.116; extra == 'server'
Requires-Dist: markdown-it-py<5,>=4; extra == 'server'
Requires-Dist: mdit-py-plugins<0.7,>=0.5; extra == 'server'
Requires-Dist: pillow<13,>=12; extra == 'server'
Requires-Dist: pydantic-settings<3,>=2.10; extra == 'server'
Requires-Dist: pypdf<7,>=6.16.2; extra == 'server'
Requires-Dist: python-multipart<1,>=0.0.20; extra == 'server'
Requires-Dist: pyyaml<7,>=6; extra == 'server'
Requires-Dist: sqlalchemy<3,>=2.0; extra == 'server'
Requires-Dist: tinycss2<2,>=1.5; extra == 'server'
Requires-Dist: uvicorn<1,>=0.35; extra == 'server'
Provides-Extra: standalone
Requires-Dist: alembic<2,>=1.16; extra == 'standalone'
Requires-Dist: argon2-cffi<26,>=25.1; extra == 'standalone'
Requires-Dist: cairosvg<3,>=2.8; extra == 'standalone'
Requires-Dist: fastapi<1,>=0.116; extra == 'standalone'
Requires-Dist: markdown-it-py<5,>=4; extra == 'standalone'
Requires-Dist: mdit-py-plugins<0.7,>=0.5; extra == 'standalone'
Requires-Dist: pillow<13,>=12; extra == 'standalone'
Requires-Dist: pydantic-settings<3,>=2.10; extra == 'standalone'
Requires-Dist: pypdf<7,>=6.16.2; extra == 'standalone'
Requires-Dist: python-multipart<1,>=0.0.20; extra == 'standalone'
Requires-Dist: pyyaml<7,>=6; extra == 'standalone'
Requires-Dist: sqlalchemy<3,>=2.0; extra == 'standalone'
Requires-Dist: tinycss2<2,>=1.5; extra == 'standalone'
Requires-Dist: uvicorn<1,>=0.35; extra == 'standalone'
Description-Content-Type: text/markdown

<p align="center"><img src="web/public/markweave-logo.png" alt="Markweave" width="320"></p>

# Markweave: Markdown to DOCX and PDF

Markweave turns a Markdown file into DOCX, PDF, or an editable PowerPoint presentation from a small browser interface. It keeps
your Word and PowerPoint templates and completed jobs on local persistent storage. It scans every upload with
ClamAV by default and can explicitly delegate that boundary to a trusted upstream proxy.

The project is licensed under [Apache-2.0](LICENSE). The source package version is `0.7.2`.
The default public quickstart remains pinned to the matched published `0.7.1` backend and Next.js
frontend pair until 0.7.2 publication completes and records new receipts. Do not substitute
candidate or inferred digests; candidate testing may override both image references together with
another matched immutable pair.

The [documentation index](docs/index.md) provides longer guides organized by role. You do not need
to read them before trying the local profile.

## Try it locally

You need OpenSSL, `flock`, about 6 GiB of available memory, and Docker Compose or
rootless Podman with a Compose provider. Published images support Linux/AMD64.

```bash
git clone https://github.com/Guillaume-Lombardo/simple-md-to-docx-converter.git
cd simple-md-to-docx-converter
scripts/quickstart-simple.sh up
scripts/quickstart-simple.sh password
```

Open <http://localhost:8080> and sign in as `admin` with the displayed password.
In **2docx**, upload `examples/quickstart-source.md`, keep **Pandoc default**,
choose DOCX, PDF, or both, and start the conversion. Download the result when ready.
The first startup can take several minutes while ClamAV loads its signatures.

```bash
scripts/quickstart-simple.sh ps
scripts/quickstart-simple.sh logs
scripts/quickstart-simple.sh down
```

Normal shutdown preserves accounts, templates, results and the administrator password.
Results in this evaluation profile expire after 10 minutes.

This is a **local evaluation profile**, bound to loopback. Its disposable `/work` volume
has no physical capacity cap. Do not expose it as a production service. The
[quickstart operations guide](docs/quickstart.md) explains the bounded secure profile,
Docker/Podman selection, custom ports and HTTPS proxy origins, Word templates, recovery,
and the explicit trusted-upstream and insecure SSH-tunnel modes with their restrictions.

## Use and operate Markweave

- [Command-line interface](docs/cli.md)
- [Python package and optional dependencies](docs/python-distribution.md)
- [Provision users from a startup CSV and require password renewal](docs/authentication.md#startup-csv-provisioning)
- [Conversion interface](docs/conversion-ui.md)
- [PowerPoint and Marp workflow](docs/powerpoint.md)
- [Template administration](docs/administration-ui.md)
- [Supported Markdown and DOCX behavior](docs/pandoc-docx.md)
- [Word templates and fonts](docs/word-templates-fonts.md)
- [Jobs, cancellation, retention, and recovery](docs/jobs.md)
- [Logs, metrics, audit, and readiness](docs/observability.md)
- [Release and image update process](docs/releasing.md)
- [Upgrade and rollback guidance](docs/upgrading.md)
- [Changelog](CHANGELOG.md)
- [Security policy](SECURITY.md)
- [Support policy](SUPPORT.md)

## How it works

The browser and HTTP API authenticate a local user, validate and scan the upload, and record a
durable conversion job. A worker claims that job with a renewable lease, resolves the exact
immutable template version when one was selected (or uses Pandoc's built-in default reference
document), and runs the local Pandoc, Chromium/Mermaid, and LibreOffice engines inside bounded
workspaces. Results and traceability metadata are retained for the configured period; document
content is not written to logs.

The standalone profile used by Compose keeps SQLite metadata and atomic objects under one `/data`
volume and runs one embedded worker. The distributed profile separates API and worker processes,
using PostgreSQL and S3-compatible object storage so workers can scale independently. Both profiles
share the same authorization, queue, validation, and retention contracts. See the
[architecture guide](docs/architecture.md), [API guide](docs/api-guide.md), and
[complete configuration reference](docs/configuration.md) for the deeper design.

## Develop and contribute

Development targets Python 3.14 and uses `uv`, Ruff, `ty`, Pytest, and the repository's locked
toolchain. Install all groups, then run the canonical checks:

```bash
uv sync --all-groups
uv run ruff format --check .
uv run ruff check .
uv run ty check
scripts/javascript/bootstrap-pnpm.sh "$PWD/.pnpm-tools"
export PATH="$PWD/.pnpm-tools/bin:$PATH"
export COREPACK_HOME="$PWD/.pnpm-tools/corepack-home" COREPACK_ENABLE_NETWORK=0
pnpm install --frozen-lockfile --ignore-scripts
pnpm run test:web
uv run pytest -m "not requires_pandoc and not requires_mermaid and not requires_libreoffice"
uv run pytest
```

Read [CONTRIBUTING.md](CONTRIBUTING.md) and the normative
[product specification](docs/product-specification.md) before changing behavior. The
[local-development guide](docs/local-development.md) covers the repository layout and deeper setup;
the [release guide](docs/releasing.md) covers protected PyPI and GHCR publication.
