Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

= AsciiDoctype
:toc: left
:toc-title: Contents
:toclevels: 3
:icons: font
:source-highlighter: highlight.js
:description: A standalone, pure-Python HTML5 and XHTML rendering library for AsciiDoctrine ASG dictionaries.

image:https://img.shields.io/badge/License-Apache%202.0-blue.svg[Apache 2.0 License, link=LICENSE.adoc]
image:https://img.shields.io/badge/python-%3E%3D3.10-green[Python 3.10+]
image:https://img.shields.io/badge/chameleon-%3E%3D4.0-orange[Chameleon 4.0+]
image:https://img.shields.io/badge/latex2mathml-%3E%3D3.77-purple[latex2mathml 3.77+]
image:https://img.shields.io/badge/asciidoctrine-%3E%3D0.1.0a12-blue[AsciiDoctrine 0.1.0a12+]
image:https://img.shields.io/pypi/v/asciidoctype.svg[PyPI, link=https://pypi.org/project/asciidoctype/]

AsciiDoctype is a **headless, pure-Python rendering library** that lowers the
Resolved Abstract Semantic Graph (ASG) produced by
https://github.com/asciidoctor/asciidoctrine[AsciiDoctrine] into valid,
well-formed HTML5 or strict XHTML markup.

It is the designated rendering layer in the **AsciiDoctrine ecosystem** — sitting
between the semantic parser and any downstream orchestrator (Golem SSG, EPUB
compilers, custom toolchains).

....
+--------------------+ +------------------+ +---------------------+
| AsciiDoctrine | ───> | AsciiDoctype | ───> | Golem / EPUB / |
| (Pure Semantic ASG)| | (Chameleon ZPT) | | Custom Tool |
+--------------------+ +------------------+ +---------------------+
....

== Why AsciiDoctype?

[cols="1,3",options="header"]
|===
|Principle |Explanation

|*Headless*
|Ships zero CSS, zero JavaScript, zero styling opinions. Markup is clean,
un-styled semantic HTML ready for any design system downstream.

|*Themeable*
|Custom themes supply their own Chameleon (ZPT) templates. AsciiDoctype
resolves user templates first and falls back to its bundled core templates
automatically.

|*Dual-pipeline*
|Identical ASG dictionaries render cleanly to either HTML5 (browser-native)
or XHTML 1.0 Strict (EPUB/Kindle-safe) with a single constructor flag.

|*Bytecode speed*
|Powered by https://chameleon.readthedocs.io/[Chameleon], which pre-compiles
templates to native Python bytecode. Recursive tree rendering is fast even on
deeply nested documents.

|*Clean boundaries*
|AsciiDoctype never touches the filesystem beyond template lookup. No file I/O,
no CSS injection, no link validation — each concern lives in the correct layer.

|*Native MathML*
|Converts LaTeX math (latexmath) to native MathML markup at render time via latex2mathml. No downstream JavaScript dependencies like MathJax or KaTeX needed.
|===

== Quick Start

=== Installation

[source,bash]
----
pip install asciidoctype
----

Or in development mode:

[source,bash]
----
git clone https://github.com/webmaven/asciidoctype.git
cd asciidoctype
python -m venv .venv && source .venv/bin/activate
pip install -e .[test]
----

=== Minimal Usage

[source,python]
----
from asciidoctype import AsciiDoctypeRenderer

renderer = AsciiDoctypeRenderer(target_format="html5")

# An ASG node dictionary as produced by AsciiDoctrine's to_dict()
node = {
"name": "paragraph",
"type": "block",
"attributes": {},
"inlines": [
{"name": "text", "type": "string", "value": "Hello, "},
{
"name": "span",
"type": "inline",
"variant": "strong",
"inlines": [{"name": "text", "type": "string", "value": "world"}],
},
{"name": "text", "type": "string", "value": "!"},
],
}

html = renderer.render(node)
# → '<p>Hello, <strong>world</strong>!</p>'
----

=== Rendering a Complete Document

[source,python]
----
from asciidoctype import AsciiDoctypeRenderer

renderer = AsciiDoctypeRenderer(target_format="html5")

document_node = {
"name": "document",
"type": "block",
"header": {"title": "My Document"},
"blocks": [
{
"name": "section",
"type": "block",
"level": 1,
"attributes": {"id": "intro"},
"title": [{"name": "text", "type": "string", "value": "Introduction"}],
"blocks": [
{
"name": "paragraph",
"type": "block",
"attributes": {},
"inlines": [
{"name": "text", "type": "string", "value": "Welcome."}
],
}
],
}
],
}

html = renderer.render(document_node)
----

=== Using a Custom Theme

Supply an ordered list of `Path` objects. AsciiDoctype resolves templates in
order, falling back to its bundled templates for any file not found in the
custom directories.

[source,python]
----
from pathlib import Path
from asciidoctype import AsciiDoctypeRenderer

renderer = AsciiDoctypeRenderer(
target_format="html5",
search_paths=[
Path("./my_site/overrides"), # highest priority
Path("./themes/my_theme"), # secondary theme
],
)
----

If `my_site/overrides/paragraph.html` exists it is used; otherwise
`themes/my_theme/paragraph.html` is tried; otherwise the bundled
`core_templates/html5/paragraph.html` is used.

== XHTML (EPUB) Mode

[source,python]
----
renderer = AsciiDoctypeRenderer(target_format="xhtml")
----

XHTML mode produces:

* `<?xml version="1.0" encoding="UTF-8"?>` declaration
* `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ...>` DOCTYPE
* `<html xmlns="http://www.w3.org/1999/xhtml">` namespace binding
* Explicit `<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />`
* All void elements closed: `<br />`, `<img />`, `<meta />`

== API Reference

=== `AsciiDoctypeRenderer`

[source,python]
----
class AsciiDoctypeRenderer:
def __init__(
self,
target_format: str = "html5",
search_paths: Optional[List[Path]] = None,
) -> None: ...

def render(
self,
node: Dict[str, Any],
context: Optional[Dict[str, Any]] = None,
) -> str: ...
----

`target_format`::
`"html5"` (default) or `"xhtml"`. Raises `ValueError` for any other value.

`search_paths`::
Ordered list of `Path` objects for template override directories. The bundled
core templates are always appended last as the final fallback.

`render(node, context=None)`::
Recursively renders an ASG node dictionary and returns a markup string.
Raises `TypeError` if `node` is not a dict with a `"name"` key.
Raises `AsciiDoctypeRenderingError` if template execution fails.

=== `AsciiDoctypeRenderingError`

Raised when a Chameleon template fails during rendering. The message includes
the node name, target pipeline, and the underlying error for quick diagnosis.

[source,python]
----
from asciidoctype import AsciiDoctypeRenderingError

try:
html = renderer.render(bad_node)
except AsciiDoctypeRenderingError as e:
print(e)
# Critical rendering failure processing structural node entity: 'listing'
# Target Specification Pipeline: [html5]. Base Error: ...
----

== Project Links

* PyPI: https://pypi.org/project/asciidoctype/
* Source: https://github.com/webmaven/asciidoctype
* Issues: https://github.com/webmaven/asciidoctype/issues
* License: link:LICENSE.adoc[Apache 2.0]
* Changelog: link:CHANGELOG.adoc[CHANGELOG.adoc]
* Architecture: link:ARCHITECTURE.adoc[ARCHITECTURE.adoc] — design, internals, ASG schemas
* Developer Guide: link:AGENTS.adoc[AGENTS.adoc] — development setup, standards, and workflows
* Contributing: link:CONTRIBUTING.adoc[CONTRIBUTING.adoc] — how to submit changes

Release files for asciidoctype 0.1.0a1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for asciidoctype 0.1.0a1
File Size Uploaded
asciidoctype-0.1.0a1.tar.gz 27.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for asciidoctype 0.1.0a1
File Interpreter ABI Platform
asciidoctype-0.1.0a1-py3-none-any.whl Python 3 none any Details

Total release size: 67.8 kB

Release files / asciidoctype-0.1.0a1.tar.gz

Download URL asciidoctype-0.1.0a1.tar.gz
Size 27.3 kB
Tags Source
SHA-256 checksum
How to use checksums
80c3d8217954262385bfbf11c5a276b268007dddb1ebce89d0f3010a929228de
BLAKE2b-256 checksum
How to use checksums
6aaf07c9abac3638661fa091a18317eef383b02691b91044b1fabe81aba2d794
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.5

Release files / asciidoctype-0.1.0a1-py3-none-any.whl

Download URL asciidoctype-0.1.0a1-py3-none-any.whl
Size 40.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f6aa344716a8ef3d055b6b6bc6b615cbdbdeaa5bd73f57d1ab6f79728422f9b5
BLAKE2b-256 checksum
How to use checksums
19206a0ca5e42b3bdefde0e602e471003cd2a15f4de4834c22c77e98b6d5868e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.5
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page