synthkit 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,59 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ build:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - name: Install uv
17
+ uses: astral-sh/setup-uv@v4
18
+
19
+ - name: Set up Python
20
+ run: uv python install 3.12
21
+
22
+ - name: Build package
23
+ run: uv build
24
+
25
+ - name: Upload build artifacts
26
+ uses: actions/upload-artifact@v4
27
+ with:
28
+ name: dist
29
+ path: dist/
30
+
31
+ test:
32
+ runs-on: ubuntu-latest
33
+ steps:
34
+ - uses: actions/checkout@v4
35
+
36
+ - name: Install uv
37
+ uses: astral-sh/setup-uv@v4
38
+
39
+ - name: Set up Python
40
+ run: uv python install 3.12
41
+
42
+ - name: Run tests
43
+ run: uv run --extra dev pytest -v
44
+
45
+ publish:
46
+ needs: [build, test]
47
+ runs-on: ubuntu-latest
48
+ environment: pypi
49
+ permissions:
50
+ id-token: write
51
+ steps:
52
+ - name: Download build artifacts
53
+ uses: actions/download-artifact@v4
54
+ with:
55
+ name: dist
56
+ path: dist/
57
+
58
+ - name: Publish to PyPI
59
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,91 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ lint:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - name: Install uv
19
+ uses: astral-sh/setup-uv@v4
20
+
21
+ - name: Set up Python
22
+ run: uv python install 3.12
23
+
24
+ - name: Ruff lint
25
+ run: uv run --extra dev ruff check src/ tests/
26
+
27
+ - name: Ruff format
28
+ run: uv run --extra dev ruff format --check src/ tests/
29
+
30
+ typecheck:
31
+ runs-on: ubuntu-latest
32
+ steps:
33
+ - uses: actions/checkout@v4
34
+
35
+ - name: Install uv
36
+ uses: astral-sh/setup-uv@v4
37
+
38
+ - name: Set up Python
39
+ run: uv python install 3.12
40
+
41
+ - name: Mypy
42
+ run: uv run --extra dev mypy
43
+
44
+ test:
45
+ runs-on: ${{ matrix.os }}
46
+ strategy:
47
+ fail-fast: false
48
+ matrix:
49
+ os: [ubuntu-latest, macos-latest, windows-latest]
50
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
51
+ steps:
52
+ - uses: actions/checkout@v4
53
+
54
+ - name: Install uv
55
+ uses: astral-sh/setup-uv@v4
56
+
57
+ - name: Set up Python ${{ matrix.python-version }}
58
+ run: uv python install ${{ matrix.python-version }}
59
+
60
+ - name: Run tests
61
+ run: uv run --extra dev pytest -v
62
+
63
+ coverage:
64
+ runs-on: ubuntu-latest
65
+ steps:
66
+ - uses: actions/checkout@v4
67
+
68
+ - name: Install uv
69
+ uses: astral-sh/setup-uv@v4
70
+
71
+ - name: Set up Python
72
+ run: uv python install 3.12
73
+
74
+ - name: Run tests with coverage
75
+ run: |
76
+ uv run --extra dev pytest --cov=synthkit --cov-report=term | tee coverage-output.txt
77
+ COVERAGE=$(grep '^TOTAL' coverage-output.txt | awk '{print $NF}' | tr -d '%')
78
+ echo "COVERAGE=$COVERAGE" >> $GITHUB_ENV
79
+
80
+ - name: Update coverage badge
81
+ if: github.ref == 'refs/heads/main' && github.event_name == 'push'
82
+ uses: schneegans/dynamic-badges-action@v1.7.0
83
+ with:
84
+ auth: ${{ secrets.GIST_TOKEN }}
85
+ gistID: ${{ vars.COVERAGE_GIST_ID }}
86
+ filename: synthkit-coverage.json
87
+ label: coverage
88
+ message: ${{ env.COVERAGE }}%
89
+ valColorRange: ${{ env.COVERAGE }}
90
+ minColorRange: 50
91
+ maxColorRange: 100
@@ -0,0 +1,9 @@
1
+ mermaid-filter.err
2
+ __pycache__/
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ *.pyc
7
+ .venv/
8
+ .coverage
9
+ .pytest_cache/
@@ -0,0 +1,68 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ Synthkit is a Python package for converting AI-generated Markdown (from Claude, Gemini, etc.) into production-ready documents. It provides a unified CLI (`synthkit doc/email/html/pdf`) and backward-compatible standalone commands (`md2doc`, `md2email`, `md2html`, `md2pdf`). Installable via `uvx synthkit` or `pip install synthkit`.
8
+
9
+ ## Repository Structure
10
+
11
+ - **`src/synthkit/`**: Python package source
12
+ - `cli.py` — Click CLI with subcommands and standalone entry points
13
+ - `base.py` — Shared logic (format building, config discovery, batch processing, pandoc invocation)
14
+ - `doc.py` — Markdown → Word (.docx) via pandoc
15
+ - `email.py` — Markdown → clipboard (HTML/RTF, cross-platform via pyperclip)
16
+ - `html.py` — Markdown → HTML via pandoc
17
+ - `pdf.py` — Markdown → PDF via pandoc + weasyprint
18
+ - **`pyproject.toml`**: Package config (hatchling build, click+pypandoc_binary+pyperclip+weasyprint deps)
19
+ - **`style.css`**: Default stylesheet bundled with the package
20
+ - **`prompt-templates/`**: Prompt templates for AI interaction use cases
21
+ - **`guidelines/`**: Reference guidelines and standards
22
+
23
+ ## Development
24
+
25
+ ```bash
26
+ # Install in development mode
27
+ uv pip install -e .
28
+
29
+ # Run directly
30
+ uv run synthkit html example.md
31
+ uv run md2html example.md
32
+ ```
33
+
34
+ ## Architecture
35
+
36
+ - All converters share `base.py` logic: pandoc format string (`markdown+lists_without_preceding_blankline` ± `hard_line_breaks`), config file discovery under `~/.config/<toolname>/`, batch processing with success/fail counting.
37
+ - Mermaid diagram support is opt-in via `--mermaid` flag (requires `mermaid-filter` installed externally).
38
+ - `email.py` is cross-platform: uses `textutil`+`pbcopy` on macOS for RTF clipboard, falls back to `pyperclip` (HTML) on other platforms.
39
+ - `pdf.py` uses `--pdf-engine=weasyprint` (CSS-styled, no LaTeX needed). Config via `~/.config/md2pdf/style.css`.
40
+ - Entry points defined in `pyproject.toml`: `synthkit` (unified CLI group), plus `md2doc`/`md2email`/`md2html`/`md2pdf` (standalone).
41
+
42
+ ## Testing
43
+
44
+ Uses pytest. Tests are in `tests/` with shared fixtures in `conftest.py`.
45
+
46
+ ```bash
47
+ uv run --extra dev pytest # run all tests
48
+ uv run --extra dev pytest -v # verbose
49
+ uv run --extra dev pytest -k base # run specific module
50
+ ```
51
+
52
+ Tests use mocking for pandoc/clipboard calls. Integration tests in `test_cli.py::TestIntegration` run actual pandoc via the bundled binary.
53
+
54
+ ## Key Dependencies
55
+
56
+ ### Python (pip-installed automatically)
57
+ - **click** (CLI framework)
58
+ - **pypandoc_binary** (bundles pandoc binary)
59
+ - **pyperclip** (cross-platform clipboard)
60
+ - **weasyprint** (PDF engine)
61
+
62
+ ### System (required for PDF only)
63
+ - **pango**, **cairo**, **gobject** — required by weasyprint
64
+ - macOS: `brew install pango`
65
+ - Ubuntu/Debian: `apt install libpango1.0-dev libcairo2-dev libgdk-pixbuf2.0-dev`
66
+
67
+ ### External (optional)
68
+ - **mermaid-filter** (Mermaid diagram rendering, opt-in via `--mermaid` flag)
@@ -0,0 +1,165 @@
1
+ Metadata-Version: 2.4
2
+ Name: synthkit
3
+ Version: 0.1.0
4
+ Summary: Convert AI-generated Markdown into production-ready documents
5
+ License-Expression: MIT
6
+ Requires-Python: >=3.10
7
+ Requires-Dist: click
8
+ Requires-Dist: pypandoc-binary
9
+ Requires-Dist: pyperclip
10
+ Requires-Dist: weasyprint
11
+ Provides-Extra: dev
12
+ Requires-Dist: mypy; extra == 'dev'
13
+ Requires-Dist: pytest; extra == 'dev'
14
+ Requires-Dist: pytest-cov; extra == 'dev'
15
+ Requires-Dist: ruff; extra == 'dev'
16
+ Description-Content-Type: text/markdown
17
+
18
+ # Synthkit
19
+
20
+ [![PyPI](https://img.shields.io/pypi/v/synthkit.svg)](https://pypi.org/project/synthkit/)
21
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
22
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://opensource.org/licenses/MIT)
23
+ [![Tests](https://github.com/rappdw/synthkit/actions/workflows/tests.yml/badge.svg)](https://github.com/rappdw/synthkit/actions/workflows/tests.yml)
24
+ [![Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/rappdw/02d0a91962d09fd9473da34fccd76237/raw/synthkit-coverage.json)](https://github.com/rappdw/synthkit/actions/workflows/tests.yml)
25
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
26
+ [![Checked with mypy](https://www.mypy-lang.org/static/mypy_badge.svg)](https://mypy-lang.org/)
27
+
28
+ A "last-mile" toolkit for working with generative AI. Synthkit bridges the gap between raw LLM output and production-ready deliverables through:
29
+
30
+ - **Document conversion** — Transform AI-generated Markdown into Word, HTML, PDF, or clipboard-ready email
31
+ - **Prompt templates** — Curated templates for structured AI interactions (reports, emails, analysis)
32
+ - **Guidelines** — Reference standards and style guides to steer AI output quality
33
+
34
+ ## Document Conversion
35
+
36
+ ### Installation
37
+
38
+ ```bash
39
+ # Run directly with uvx (no install needed)
40
+ uvx synthkit html document.md
41
+
42
+ # Or install globally
43
+ uv tool install synthkit
44
+
45
+ # Or install with pip
46
+ pip install synthkit
47
+ ```
48
+
49
+ Pandoc is bundled automatically via [`pypandoc_binary`](https://pypi.org/project/pypandoc-binary/) — no separate install needed.
50
+
51
+ #### System dependencies for PDF
52
+
53
+ PDF conversion uses [WeasyPrint](https://weasyprint.org/), which requires system libraries:
54
+
55
+ | Platform | Install command |
56
+ |----------|----------------|
57
+ | **macOS** | `brew install pango` |
58
+ | **Ubuntu/Debian** | `apt install libpango1.0-dev libcairo2-dev libgdk-pixbuf2.0-dev` |
59
+ | **Windows** | See [WeasyPrint docs](https://doc.courtbouillon.org/weasyprint/stable/first_steps.html#windows) |
60
+
61
+ `doc`, `html`, and `email` commands work without these.
62
+
63
+ ### Usage
64
+
65
+ #### Unified CLI
66
+
67
+ ```bash
68
+ synthkit doc report.md # → report.docx
69
+ synthkit html report.md # → report.html
70
+ synthkit pdf report.md # → report.pdf
71
+ synthkit email report.md # → clipboard
72
+
73
+ # Batch processing
74
+ synthkit doc *.md
75
+ synthkit html *.md --hard-breaks
76
+
77
+ # Mermaid diagrams (requires mermaid-filter)
78
+ synthkit html report.md --mermaid
79
+ ```
80
+
81
+ #### Backward-compatible commands
82
+
83
+ ```bash
84
+ md2doc report.md
85
+ md2html report.md
86
+ md2pdf report.md
87
+ md2email report.md
88
+ ```
89
+
90
+ #### Options
91
+
92
+ | Flag | Description |
93
+ |------|-------------|
94
+ | `--hard-breaks` | Preserve line breaks from source markdown |
95
+ | `--mermaid` | Enable Mermaid diagram rendering (requires [`mermaid-filter`](https://github.com/raghur/mermaid-filter)) |
96
+
97
+ ### Configuration
98
+
99
+ Each converter looks for optional config files under `~/.config/<toolname>/`:
100
+
101
+ | Converter | Config Files |
102
+ |-----------|-------------|
103
+ | `doc` | `~/.config/md2doc/reference.docx` |
104
+ | `email` | `~/.config/md2email/style.css` |
105
+ | `html` | `~/.config/md2html/style.css` |
106
+ | `pdf` | `~/.config/md2pdf/style.css` |
107
+
108
+ ## Prompt Templates
109
+
110
+ The `prompt-templates/` directory contains curated prompt templates for structured AI interactions. These are optimized for Markdown-first responses to ensure compatibility with the document conversion tools.
111
+
112
+ Copy the contents of any template into your LLM of choice (Claude, Gemini, ChatGPT, etc.) to get consistently structured output ready for conversion.
113
+
114
+ ## Guidelines
115
+
116
+ The `guidelines/` directory contains reference standards and style guides that can be provided as context to AI models to steer output quality and consistency.
117
+
118
+ ## Testing
119
+
120
+ ```bash
121
+ # Run tests
122
+ uv run --extra dev pytest
123
+
124
+ # With coverage
125
+ uv run --extra dev pytest --cov=synthkit --cov-report=term-missing
126
+ ```
127
+
128
+ Tests run automatically on push/PR to `main` across Python 3.10-3.13 on Linux, macOS, and Windows.
129
+
130
+ ## Repository Structure
131
+
132
+ ```
133
+ ├── .github/workflows/
134
+ │ ├── tests.yml # CI: test on push/PR to main
135
+ │ └── publish.yml # CD: publish to PyPI on release
136
+ ├── pyproject.toml
137
+ ├── src/synthkit/ # Python package
138
+ │ ├── cli.py # Click CLI with subcommands
139
+ │ ├── base.py # Shared conversion logic
140
+ │ ├── doc.py # Word conversion
141
+ │ ├── email.py # Email clipboard conversion
142
+ │ ├── html.py # HTML conversion
143
+ │ └── pdf.py # PDF conversion (via WeasyPrint)
144
+ ├── tests/ # Test suite (pytest)
145
+ │ ├── conftest.py # Shared fixtures
146
+ │ ├── test_base.py # Base module tests
147
+ │ ├── test_cli.py # CLI + integration tests
148
+ │ ├── test_doc.py # Word converter tests
149
+ │ ├── test_email.py # Email converter tests
150
+ │ ├── test_html.py # HTML converter tests
151
+ │ └── test_pdf.py # PDF converter tests
152
+ ├── style.css # Default stylesheet
153
+ ├── prompt-templates/ # AI interaction prompt templates
154
+ └── guidelines/ # Reference guidelines
155
+ ```
156
+
157
+ ## Dependencies
158
+
159
+ | Package | Purpose | Bundled? |
160
+ |---------|---------|----------|
161
+ | [`click`](https://click.palletsprojects.com/) | CLI framework | pip |
162
+ | [`pypandoc_binary`](https://pypi.org/project/pypandoc-binary/) | Pandoc document converter | pip (includes binary) |
163
+ | [`pyperclip`](https://pypi.org/project/pyperclip/) | Cross-platform clipboard | pip |
164
+ | [`weasyprint`](https://weasyprint.org/) | PDF engine | pip (needs system libs) |
165
+ | [`mermaid-filter`](https://github.com/raghur/mermaid-filter) | Mermaid diagrams | Optional, external |
@@ -0,0 +1,148 @@
1
+ # Synthkit
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/synthkit.svg)](https://pypi.org/project/synthkit/)
4
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
5
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://opensource.org/licenses/MIT)
6
+ [![Tests](https://github.com/rappdw/synthkit/actions/workflows/tests.yml/badge.svg)](https://github.com/rappdw/synthkit/actions/workflows/tests.yml)
7
+ [![Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/rappdw/02d0a91962d09fd9473da34fccd76237/raw/synthkit-coverage.json)](https://github.com/rappdw/synthkit/actions/workflows/tests.yml)
8
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
9
+ [![Checked with mypy](https://www.mypy-lang.org/static/mypy_badge.svg)](https://mypy-lang.org/)
10
+
11
+ A "last-mile" toolkit for working with generative AI. Synthkit bridges the gap between raw LLM output and production-ready deliverables through:
12
+
13
+ - **Document conversion** — Transform AI-generated Markdown into Word, HTML, PDF, or clipboard-ready email
14
+ - **Prompt templates** — Curated templates for structured AI interactions (reports, emails, analysis)
15
+ - **Guidelines** — Reference standards and style guides to steer AI output quality
16
+
17
+ ## Document Conversion
18
+
19
+ ### Installation
20
+
21
+ ```bash
22
+ # Run directly with uvx (no install needed)
23
+ uvx synthkit html document.md
24
+
25
+ # Or install globally
26
+ uv tool install synthkit
27
+
28
+ # Or install with pip
29
+ pip install synthkit
30
+ ```
31
+
32
+ Pandoc is bundled automatically via [`pypandoc_binary`](https://pypi.org/project/pypandoc-binary/) — no separate install needed.
33
+
34
+ #### System dependencies for PDF
35
+
36
+ PDF conversion uses [WeasyPrint](https://weasyprint.org/), which requires system libraries:
37
+
38
+ | Platform | Install command |
39
+ |----------|----------------|
40
+ | **macOS** | `brew install pango` |
41
+ | **Ubuntu/Debian** | `apt install libpango1.0-dev libcairo2-dev libgdk-pixbuf2.0-dev` |
42
+ | **Windows** | See [WeasyPrint docs](https://doc.courtbouillon.org/weasyprint/stable/first_steps.html#windows) |
43
+
44
+ `doc`, `html`, and `email` commands work without these.
45
+
46
+ ### Usage
47
+
48
+ #### Unified CLI
49
+
50
+ ```bash
51
+ synthkit doc report.md # → report.docx
52
+ synthkit html report.md # → report.html
53
+ synthkit pdf report.md # → report.pdf
54
+ synthkit email report.md # → clipboard
55
+
56
+ # Batch processing
57
+ synthkit doc *.md
58
+ synthkit html *.md --hard-breaks
59
+
60
+ # Mermaid diagrams (requires mermaid-filter)
61
+ synthkit html report.md --mermaid
62
+ ```
63
+
64
+ #### Backward-compatible commands
65
+
66
+ ```bash
67
+ md2doc report.md
68
+ md2html report.md
69
+ md2pdf report.md
70
+ md2email report.md
71
+ ```
72
+
73
+ #### Options
74
+
75
+ | Flag | Description |
76
+ |------|-------------|
77
+ | `--hard-breaks` | Preserve line breaks from source markdown |
78
+ | `--mermaid` | Enable Mermaid diagram rendering (requires [`mermaid-filter`](https://github.com/raghur/mermaid-filter)) |
79
+
80
+ ### Configuration
81
+
82
+ Each converter looks for optional config files under `~/.config/<toolname>/`:
83
+
84
+ | Converter | Config Files |
85
+ |-----------|-------------|
86
+ | `doc` | `~/.config/md2doc/reference.docx` |
87
+ | `email` | `~/.config/md2email/style.css` |
88
+ | `html` | `~/.config/md2html/style.css` |
89
+ | `pdf` | `~/.config/md2pdf/style.css` |
90
+
91
+ ## Prompt Templates
92
+
93
+ The `prompt-templates/` directory contains curated prompt templates for structured AI interactions. These are optimized for Markdown-first responses to ensure compatibility with the document conversion tools.
94
+
95
+ Copy the contents of any template into your LLM of choice (Claude, Gemini, ChatGPT, etc.) to get consistently structured output ready for conversion.
96
+
97
+ ## Guidelines
98
+
99
+ The `guidelines/` directory contains reference standards and style guides that can be provided as context to AI models to steer output quality and consistency.
100
+
101
+ ## Testing
102
+
103
+ ```bash
104
+ # Run tests
105
+ uv run --extra dev pytest
106
+
107
+ # With coverage
108
+ uv run --extra dev pytest --cov=synthkit --cov-report=term-missing
109
+ ```
110
+
111
+ Tests run automatically on push/PR to `main` across Python 3.10-3.13 on Linux, macOS, and Windows.
112
+
113
+ ## Repository Structure
114
+
115
+ ```
116
+ ├── .github/workflows/
117
+ │ ├── tests.yml # CI: test on push/PR to main
118
+ │ └── publish.yml # CD: publish to PyPI on release
119
+ ├── pyproject.toml
120
+ ├── src/synthkit/ # Python package
121
+ │ ├── cli.py # Click CLI with subcommands
122
+ │ ├── base.py # Shared conversion logic
123
+ │ ├── doc.py # Word conversion
124
+ │ ├── email.py # Email clipboard conversion
125
+ │ ├── html.py # HTML conversion
126
+ │ └── pdf.py # PDF conversion (via WeasyPrint)
127
+ ├── tests/ # Test suite (pytest)
128
+ │ ├── conftest.py # Shared fixtures
129
+ │ ├── test_base.py # Base module tests
130
+ │ ├── test_cli.py # CLI + integration tests
131
+ │ ├── test_doc.py # Word converter tests
132
+ │ ├── test_email.py # Email converter tests
133
+ │ ├── test_html.py # HTML converter tests
134
+ │ └── test_pdf.py # PDF converter tests
135
+ ├── style.css # Default stylesheet
136
+ ├── prompt-templates/ # AI interaction prompt templates
137
+ └── guidelines/ # Reference guidelines
138
+ ```
139
+
140
+ ## Dependencies
141
+
142
+ | Package | Purpose | Bundled? |
143
+ |---------|---------|----------|
144
+ | [`click`](https://click.palletsprojects.com/) | CLI framework | pip |
145
+ | [`pypandoc_binary`](https://pypi.org/project/pypandoc-binary/) | Pandoc document converter | pip (includes binary) |
146
+ | [`pyperclip`](https://pypi.org/project/pyperclip/) | Cross-platform clipboard | pip |
147
+ | [`weasyprint`](https://weasyprint.org/) | PDF engine | pip (needs system libs) |
148
+ | [`mermaid-filter`](https://github.com/raghur/mermaid-filter) | Mermaid diagrams | Optional, external |
File without changes
File without changes
@@ -0,0 +1,54 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "synthkit"
7
+ version = "0.1.0"
8
+ description = "Convert AI-generated Markdown into production-ready documents"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ dependencies = [
13
+ "click",
14
+ "pypandoc_binary",
15
+ "pyperclip",
16
+ "weasyprint",
17
+ ]
18
+
19
+ [project.scripts]
20
+ synthkit = "synthkit.cli:main"
21
+ md2doc = "synthkit.cli:md2doc_cmd"
22
+ md2email = "synthkit.cli:md2email_cmd"
23
+ md2html = "synthkit.cli:md2html_cmd"
24
+ md2pdf = "synthkit.cli:md2pdf_cmd"
25
+
26
+ [project.optional-dependencies]
27
+ dev = ["pytest", "pytest-cov", "ruff", "mypy"]
28
+
29
+ [tool.pytest.ini_options]
30
+ testpaths = ["tests"]
31
+
32
+ [tool.ruff]
33
+ target-version = "py310"
34
+ src = ["src"]
35
+ line-length = 100
36
+
37
+ [tool.ruff.lint]
38
+ select = ["E", "F", "I", "UP"]
39
+
40
+ [tool.mypy]
41
+ python_version = "3.10"
42
+ mypy_path = "src"
43
+ packages = ["synthkit"]
44
+ strict = false
45
+ warn_return_any = true
46
+ warn_unused_configs = true
47
+ disallow_untyped_defs = true
48
+
49
+ [[tool.mypy.overrides]]
50
+ module = ["pypandoc", "pyperclip"]
51
+ ignore_missing_imports = true
52
+
53
+ [tool.hatch.build.targets.wheel]
54
+ packages = ["src/synthkit"]
@@ -0,0 +1,3 @@
1
+ """Synthkit: Convert AI-generated Markdown into production-ready documents."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,89 @@
1
+ """Base converter with shared logic for all Synthkit converters."""
2
+
3
+ import subprocess
4
+ import sys
5
+ from collections.abc import Callable
6
+ from pathlib import Path
7
+
8
+ import pypandoc
9
+
10
+ BASE_FORMAT = "markdown+lists_without_preceding_blankline"
11
+
12
+
13
+ def build_format(hard_breaks: bool = False) -> str:
14
+ fmt = BASE_FORMAT
15
+ if hard_breaks:
16
+ fmt += "+hard_line_breaks"
17
+ return fmt
18
+
19
+
20
+ def config_path(tool_name: str, filename: str) -> Path | None:
21
+ p = Path.home() / ".config" / tool_name / filename
22
+ return p if p.is_file() else None
23
+
24
+
25
+ def bundled_style_css() -> Path:
26
+ return Path(__file__).parent.parent.parent / "style.css"
27
+
28
+
29
+ def cleanup_mermaid_err() -> None:
30
+ err = Path("mermaid-filter.err")
31
+ if err.is_file() and err.stat().st_size == 0:
32
+ err.unlink()
33
+
34
+
35
+ def get_pandoc_bin() -> str:
36
+ return str(pypandoc.get_pandoc_path())
37
+
38
+
39
+ def run_pandoc(
40
+ args: list[str], env: dict[str, str] | None = None
41
+ ) -> subprocess.CompletedProcess[bytes]:
42
+ return subprocess.run([get_pandoc_bin(), *args], capture_output=False, env=env)
43
+
44
+
45
+ def mermaid_args(mermaid: bool) -> list[str]:
46
+ if mermaid:
47
+ return ["--filter", "mermaid-filter"]
48
+ return []
49
+
50
+
51
+ def batch_convert(
52
+ files: tuple[str, ...],
53
+ hard_breaks: bool,
54
+ mermaid: bool,
55
+ convert_one: Callable[[Path, bool, bool], None],
56
+ ) -> None:
57
+ if not files:
58
+ print("No input files provided.", file=sys.stderr)
59
+ sys.exit(1)
60
+
61
+ success = 0
62
+ fail = 0
63
+
64
+ for filepath in files:
65
+ path = Path(filepath)
66
+ if path.suffix != ".md":
67
+ print(f"Skipping non-markdown file: {filepath}")
68
+ continue
69
+ if not path.is_file():
70
+ print(f"Warning: File '{filepath}' not found, skipping.")
71
+ fail += 1
72
+ continue
73
+
74
+ try:
75
+ convert_one(path, hard_breaks, mermaid)
76
+ success += 1
77
+ except ConversionError as e:
78
+ print(f"Error: {e}")
79
+ fail += 1
80
+
81
+ if mermaid:
82
+ cleanup_mermaid_err()
83
+ print(f"\nDone: {success} succeeded, {fail} failed.")
84
+ if fail > 0:
85
+ sys.exit(1)
86
+
87
+
88
+ class ConversionError(Exception):
89
+ pass