Skip to main content

Convert Markdown to polished documents with reusable themes

Project description

docu-craft

Stop writing PDFs by hand. Write Markdown, get a polished document.

import docu_craft

docu_craft.render("report.md", theme="scholar")

What it does

You write content in Markdown. docu-craft handles everything else:

  • Picks a theme — fonts, colors, margins, tables, code blocks, all styled consistently across every output format
  • Named document styles — styles are registered as first-class named styles in DOCX and ODT, visible in Word's Styles pane and LibreOffice's Styles panel, not just inline formatting
  • Multiple output formats — PDF, HTML, DOCX, ODT, LaTeX from the same source file
  • Handles emoji — system font fallback or image replacement via downloadable emoji sets
  • Validates structure — checks that your document has the sections it needs before rendering
  • Finds your assets — themes, skeletons, and emoji sets from the package, your home folder, or any mounted path

No more pasting CSS into scripts. No more fighting with PDF libraries.


Install

pip install docu-craft

# with DOCX support
pip install "docu-craft[docx]"

# with HTML → Markdown conversion
pip install "docu-craft[html]"

# with PDF → Markdown extraction
pip install "docu-craft[pymupdf]"

# everything
pip install "docu-craft[all]"

Conversion paths

docu-craft uses a weighted DAG to resolve conversions. Ask for any path — it finds the route automatically.

From To Engine Notes
md pdf WeasyPrint (default) via HTML — full CSS, emoji font support
md pdf LaTeX via pdflatex/xelatex — requires LaTeX install
md html embedded CSS from theme
md docx named styles visible in Word's Styles pane
md odt named styles visible in LibreOffice's Styles panel
md latex direct Markdown → LaTeX source
html md extracts article body, strips chrome, preserves images
pdf md extracts structured text, infers headings from font size
doc = docu_craft.Document("report.md")
doc.apply_theme("scholar")

doc.render(format="pdf",  output="report.pdf")
doc.render(format="docx", output="report.docx")
doc.render(format="html", output="report.html")

# Convert a web paper to Markdown
doc = docu_craft.Document("paper.html")
doc.render(format="md", output="paper.md", img_dir="figures/", base_url="https://example.com/paper/")

# Extract text from a PDF
doc = docu_craft.Document("paper.pdf")
doc.render(format="md", output="paper.md")

Themes

Themes define the full visual identity of a document — fonts, colors, spacing, and every named style — applied consistently across all output formats.

Theme Best for
scholar Academic articles, PhD documents
handout Course materials, workshops
tech-doc API docs, technical references
official Institutional letters, formal reports
docu_craft.render("thesis.md", theme="scholar")
docu_craft.render("class_notes.md", theme="handout")

Drop your own theme in ~/docu_craft/themes/mytheme/ and use it the same way.

Theme schema

Every theme defines a styles block with named semantic styles — body, heading1heading6, code_block, code_inline, table_header, table_cell, list_item, quote. Each style references a font stack by name (body, header, or mono) and specifies size, color, weight, spacing, and background.

# theme.yaml
style:
  fonts:
    body:   ["Georgia", "Times New Roman", "serif"]
    header: ["Arial", "Helvetica", "sans-serif"]
    mono:   ["Courier New", "Courier", "monospace"]
    emoji:  ["Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji"]

  styles:
    heading1:
      font: header
      size: 16
      color: "#1a1a2e"
      bold: true
    code_block:
      font: mono
      size: 9
      background: "#f4f4f4"

The same style definitions drive all renderers — Word's "DC Heading 1", LibreOffice's "DC Body Text", and the CSS h1 rule all come from the same source.


Emoji

System emoji (font fallback)

By default docu-craft passes emoji through and lets the output application render them using its own font stack. For PDF via WeasyPrint, emoji fonts are resolved automatically:

# theme.yaml
style:
  fonts:
    emoji: ["Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", "Twemoji Mozilla"]

docu-craft probes the filesystem for each font (in order: Linux → macOS → Windows) and emits @font-face rules pointing to the actual font files. On WSL2, it finds Windows fonts via /mnt/c/Windows/Fonts/ automatically.

Custom emoji sets (image replacement)

For consistent, platform-independent emoji across all readers, use an image-based emoji set. Each emoji character is replaced with a PNG from the set.

docu_craft.render("notes.md", theme="scholar", emoji_set="twemoji")

Download sets with the built-in downloader:

python -m docu_craft.emoji.downloader twemoji
python -m docu_craft.emoji.downloader noto

Twemoji

The recommended custom set. Twemoji (CC-BY 4.0, by Twitter/jdecked) draws every glyph on the same grid at the same size with the same line weights. When you place several emoji side by side they read as a unified visual system — consistent weight, consistent optical size, no surprises. This is the same discipline a monospaced font applies to letterforms. If visual consistency across emoji matters in your documents, Twemoji is the right choice.

Other available sets:

Set License Coverage Character
twemoji CC-BY 4.0 3800+ Grid-locked, uniform, consistent
noto Apache 2.0 3000+ Disciplined, clean, Google design system

Skeletons

Skeletons define what sections a document should have. docu-craft tells you if something is missing before you render.

doc = docu_craft.Document("thesis.md")
doc.apply_skeleton("academic_article").validate()
doc.render()

Built-in skeletons: academic_article, plan_trabajo, tech_doc, official_letter, course_handout.


Config layers

Set defaults once, override whenever you need:

# ~/docu_craft/config.yaml — your personal defaults
defaults:
  theme: scholar
  emoji_set: twemoji
# .docu_craft.yaml — per-project overrides
defaults:
  theme: handout
---
theme: official
---
# Per-document frontmatter overrides everything above
# Explicit argument wins over all of the above
docu_craft.render("file.md", theme="tech-doc")

Extended storage

Point docu-craft at any folder — a team share, a mounted drive, a network path. It searches all of them for themes, skeletons, and emoji sets.

docu_craft.add_extended_store("/mnt/team/docu_craft-assets", name="team")
# .docu_craft.yaml
extended_stores:
  - /mnt/team/docu_craft-assets
  - path: G:/Shared/styles
    name: gdrive

Pluggable renderers

docu_craft.register_renderer(
    format="pdf",
    module_path="mypackage.renderer:MyRenderer",
    engine="myengine",
    package="mypackage",
    install="pip install mypackage",
)

doc.render(format="pdf", engine="myengine")

The renderer graph is a weighted DAG — preference between equivalent paths (e.g. md→html→pdf vs md→latex→pdf) is configured per project via the engine setting.


License

Apache 2.0 © Christian A. Servin Lozano

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

docu_craft-0.3.0.tar.gz (378.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

docu_craft-0.3.0-py3-none-any.whl (499.1 kB view details)

Uploaded Python 3

File details

Details for the file docu_craft-0.3.0.tar.gz.

File metadata

  • Download URL: docu_craft-0.3.0.tar.gz
  • Upload date:
  • Size: 378.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for docu_craft-0.3.0.tar.gz
Algorithm Hash digest
SHA256 47cf5d35e5546b1eb8d47ed4be3dadbe86191e0d3d39dcfbbc45c18a339042fb
MD5 6929c94e9b96c0846978a96c8a48c6c9
BLAKE2b-256 21e1fbc7afb2f163fcb2c7f738af906314ae5683c2f4fadf5045ca868a1fba9d

See more details on using hashes here.

Provenance

The following attestation bundles were made for docu_craft-0.3.0.tar.gz:

Publisher: publish.yml on CServinL/docu-craft

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file docu_craft-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: docu_craft-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 499.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for docu_craft-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 41ec3444166dd05c6d1e57b7b310a83f1d99764eb5baa630fbb0c1fd1bc27160
MD5 c36465f8cdb002f23a2d3821cefac3ec
BLAKE2b-256 32df096cfb032e0e7d99eb2fbd3853fa1afccc5a81e618bc3dafebd7ccbaae05

See more details on using hashes here.

Provenance

The following attestation bundles were made for docu_craft-0.3.0-py3-none-any.whl:

Publisher: publish.yml on CServinL/docu-craft

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page