Metadata-Version: 2.5
Name: markweave
Version: 0.6.4
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

# Markweave: Markdown to DOCX and PDF

Markweave turns a Markdown file into DOCX, PDF, or both from a small browser interface. It keeps
your Word 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.6.4`.
The default public quickstart pins the matched published `0.6.3` backend and Next.js frontend pair
to the immutable digests recorded in the release evidence. 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 **md 2 docx**, 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

- [Provision users from a startup CSV and require password renewal](docs/authentication.md#startup-csv-provisioning)
- [Conversion interface](docs/conversion-ui.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)

## 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.
