Python API¶
The oxydemark package is the frozen public Python surface: everything listed
in oxydemark.__all__, and nothing else. The native oxydemark._core module is
an implementation detail and must not be imported directly.
Engine and plugins¶
OxydeEngine
¶
Pipeline-oriented Markdown engine with plugin support.
The full pipeline is:
Markdown Input
-> preprocess plugins (text-level)
-> Rust parser / rushdown (AST generation)
-> transform plugins (AST-level)
-> Rust renderer (HTML generation)
-> postprocess plugins (HTML-level)
-> Final Output
Attributes:
| Name | Type | Description |
|---|---|---|
plugins |
list[Plugin]
|
The ordered plugin list the engine runs. |
Example
engine = OxydeEngine() html = engine.render("# Hello")
Build an engine.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
plugins
|
list[Plugin] | None
|
An ordered sequence of plugin instances. Each plugin may
implement |
None
|
Plugin
module-attribute
¶
Plugin: TypeAlias = Preprocessor | Transformer | Postprocessor
Any object satisfying at least one of the three plugin hooks.
Plugins may implement any combination of the hooks:
preprocess(Preprocessor): transform raw Markdown text before parsing.transform(Transformer): modify the AST between parsing and rendering.postprocess(Postprocessor): transform rendered HTML after rendering.
All hooks are optional; implement only the ones you need. Plugin is therefore
a union of the three single-hook protocols rather than a protocol requiring
all three -- most real plugins, including every one in
oxydemark.contrib, implement exactly one.
The protocols are structural and hooks are dispatched by hasattr, never
by isinstance. A plugin does not need to inherit from or register with
anything -- any object exposing at least one correctly named hook is a valid
plugin.
See oxydemark.contrib for worked examples and the
plugin authoring guide for the full picture.
Hook ordering¶
OxydeEngine runs one phase at a time across the
whole plugin list, not one plugin at a time. For plugins [A, B] the call
order is A.preprocess, B.preprocess, parse, A.transform, B.transform,
render, A.postprocess, B.postprocess.
Choosing the right hook¶
| Hook | Operates on | Use it when |
|---|---|---|
preprocess |
raw Markdown str |
the construct is not representable in the AST yet (custom markers, macros, includes, front-matter tweaks). |
transform |
AstNode tree |
you need structure: adding, removing, re-typing or annotating nodes. |
postprocess |
rendered HTML str |
the change is purely presentational and applies to the final markup. |
Escaping rules worth knowing¶
AstNode.textis HTML-escaped by the renderer.- Raw HTML present in the source Markdown is stripped: the parser
replaces it with a
<!-- raw HTML omitted -->placeholder, which is what the resulting"raw_html"/"html_block"nodes carry as theirtext. - A node of kind
"raw_html"created by a plugin emits itstextverbatim; it is the only supported way to inject markup from atransformhook.
Transformer
¶
Bases: Protocol
Plugin protocol for the AST-level transform hook.
transform
¶
Transform the AST between parsing and rendering.
AstNode has value semantics
node.children is a PyO3 getter that returns a fresh copy of the
child list, and each element in it is a copy too. Consequently:
Mutations must be applied to a local copy which is then reassigned:
def transform(self, ast):
self._modify(ast)
return ast
def _modify(self, node):
if node.kind == "text" and node.text:
node.text = node.text.upper()
children = node.children # copy out
for child in children:
self._modify(child)
node.children = children # write back -- mandatory
The same applies to AstNode.walk, which
yields copies: it is useful for inspection only, never for
mutation.
See oxydemark.contrib for complete, tested examples.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ast
|
AstNode
|
The root of the tree as produced by the previous plugin. |
required |
Returns:
| Type | Description |
|---|---|
AstNode
|
The (possibly modified) tree. |
Parsing and rendering¶
parse
¶
parse_document
¶
parse_document(markdown: str) -> ParseResult
Parse Markdown and compute structured, typed metadata (OMEP-0010).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
markdown
|
str
|
The Markdown source to parse. |
required |
Returns:
| Type | Description |
|---|---|
ParseResult
|
The AST tree bundled with the flat heading list, the nested |
ParseResult
|
table-of-contents tree, the summary HTML and typed YAML frontmatter. |
render_ast
¶
markdown_to_html
¶
Metadata helpers¶
slugify
¶
Generate a URL-friendly anchor slug from a text (OMEP-0010).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
text
|
str
|
The label to derive the slug from. |
required |
existing
|
list[str] | None
|
Already-assigned slugs, used to de-duplicate by appending a numeric suffix. |
None
|
Returns:
| Type | Description |
|---|---|
str
|
A unique, URL-friendly slug. |
extract_summary
¶
Extract the rendered-HTML summary before a top-level <!-- more --> delimiter.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
markdown
|
str
|
The Markdown source to inspect. |
required |
Returns:
| Type | Description |
|---|---|
str | None
|
The rendered summary HTML, or |
str | None
|
delimiter. |
AST and metadata types¶
AstNode
¶
AstNode(kind: str, children: list[AstNode] | None = None, text: str | None = None, attributes: dict[str, str] | None = None, metadata: dict[str, str] | None = None)
A tree-based AST node representing a Markdown element.
Attributes:
| Name | Type | Description |
|---|---|---|
kind |
str
|
The node type, such as |
children |
list[AstNode]
|
Direct child nodes. Reading this attribute returns a copy; mutations must be written back to take effect. |
text |
str | None
|
Literal text content, for leaf nodes that carry any. |
attributes |
dict[str, str]
|
Rendered HTML attributes, as strings. |
metadata |
dict[str, str] | None
|
Deprecated (OMEP-0010). Stringly-typed frontmatter, retained
for backward compatibility. Use
|
Build a node.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The node type. |
required |
children
|
list[AstNode] | None
|
Direct child nodes. |
None
|
text
|
str | None
|
Literal text content. |
None
|
attributes
|
dict[str, str] | None
|
Rendered HTML attributes. |
None
|
metadata
|
dict[str, str] | None
|
Deprecated stringly-typed frontmatter (OMEP-0010). |
None
|
props
property
¶
Typed block-component props from a leading YAML block (OMEP-0007).
Present only on block_component nodes that declare a YAML block, and
None otherwise. Values preserve their native YAML types (str,
int, float, bool, list, dict, None). Inline {…}
attributes take precedence on key collisions. Read-only.
ParseResult
¶
The AST tree plus structured, typed document metadata (OMEP-0010).
frontmatter
property
¶
Typed YAML frontmatter, or None when the document has none.
Values preserve their native YAML types (str, int, float, bool,
list, dict, None).
headings
property
¶
Every heading of the document, in document order (flat).
Heading
¶
A document heading, flat entry or TOC tree node (OMEP-0010).
children
property
¶
Nested sub-headings.
Always empty for entries of the flat
ParseResult.headings list;
populated only in ParseResult.toc.
Example plugins¶
Provisional surface
oxydemark.contrib is public and documented, but it is intentionally not
part of oxydemark.__all__ and carries no stability guarantee: these
plugins may change or be removed in a MINOR release. If you need long-term
stability, copy the plugin into your own codebase.
contrib
¶
Example plugins shipped with OxydeMark.
This namespace exists to demonstrate the Plugin protocol
against real, tested implementations. Each plugin is deliberately small and
focuses on one pipeline layer:
| Plugin | Hooks | Demonstrates |
|---|---|---|
AdmonitionPlugin |
preprocess + transform |
text normalisation, then AST enrichment |
ShortcodePlugin |
transform |
replacing text nodes with raw_html |
MentionPlugin |
transform |
splitting text into structural nodes |
LazyImagesPlugin |
postprocess |
pure HTML-string rewriting |
See the plugin authoring guide for the full picture.
Stability¶
oxydemark.contrib is a provisional surface (see OMEP-0008). It is public
and documented, but it is intentionally not part of oxydemark.__all__ and
carries no stability guarantee: these plugins may change or be removed in a
MINOR release. If you need long-term stability, copy the plugin into your own
codebase.
AdmonitionPlugin
¶
Turn GitHub-style alerts into styled admonition blocks.
Attributes:
| Name | Type | Description |
|---|---|---|
kinds |
dict[str, str]
|
The active marker-to-title mapping. |
Build the plugin.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kinds
|
Mapping[str, str] | None
|
Mapping of lowercase marker name to the title rendered in
the admonition header. Defaults to
|
None
|
preprocess
¶
ShortcodePlugin
¶
Expand {{ name argument }} markers into raw HTML nodes.
Attributes:
| Name | Type | Description |
|---|---|---|
shortcodes |
dict[str, Shortcode]
|
The active name-to-handler mapping. |
Build the plugin.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shortcodes
|
Mapping[str, Shortcode] | None
|
Mapping of shortcode name to a handler returning an
HTML fragment. Defaults to
|
None
|
MentionPlugin
¶
MentionPlugin(base_url: str = 'https://github.com/')
LazyImagesPlugin
¶
LazyImagesPlugin(decoding: str | None = 'async')
Defaults¶
The kinds= and shortcodes= arguments replace these defaults rather than
extending them; spread the mapping to add entries.