# rdx-py

Python bindings for the [RDX](https://github.com/rdx-lang/rdx) parser via [PyO3](https://pyo3.rs) and [maturin](https://www.maturin.rs). Parse `.rdx` documents at Rust speed, get plain Python dicts back.

## Installation

```sh
pip install rdx-parser
```

## Usage

```python
import rdx

ast = rdx.parse("""---
title: API Reference
---

# {$title}

<Notice type="warning">
  This endpoint is deprecated.
</Notice>
""")

print(ast["frontmatter"])  # {'title': 'API Reference'}
print(ast["children"][0]["type"])  # 'heading'
```

## API

### `rdx.parse(input: str) -> dict`

Parse an RDX document into an AST dict.

### `rdx.parse_with_defaults(input: str) -> dict`

Parse with built-in transforms (auto-slug headings + table of contents).

### `rdx.parse_with_transforms(input: str, transforms: list[str]) -> dict`

Parse with selected transforms. Available: `"auto-slug"`, `"toc"`.

### `rdx.validate(ast: dict, schema: dict) -> list[dict]`

Validate an AST against a component schema.

```python
schema = {
    "strict": True,
    "components": {
        "Notice": {
            "props": {
                "type": {"type": "enum", "required": True, "values": ["info", "warning", "error"]}
            }
        }
    }
}

diagnostics = rdx.validate(ast, schema)
for d in diagnostics:
    print(f"{d['severity']}: {d['message']} at line {d['line']}")
```

### `rdx.collect_text(ast: dict) -> str`

Extract all plain text from the AST. Useful for search indexing, embeddings, and reading time estimation.

```python
text = rdx.collect_text(ast)
words = text.split()
reading_time = len(words) // 200  # minutes
```

### `rdx.query_all(ast: dict, node_type: str) -> list[dict]`

Find all nodes of a given type.

```python
headings = rdx.query_all(ast, "heading")
components = rdx.query_all(ast, "component")
```

### `rdx.version() -> str`

Returns the RDX parser version.

## RAG / AI Pipeline Example

```python
import rdx

def prepare_for_embedding(rdx_source: str) -> list[str]:
    """Parse RDX and split into clean text chunks by heading."""
    ast = rdx.parse(rdx_source)
    chunks = []
    current = []

    for node in ast["children"]:
        if node["type"] == "heading":
            if current:
                chunks.append(rdx.collect_text({"type": "root", "frontmatter": None, "children": current, "position": ast["position"]}))
            current = [node]
        else:
            current.append(node)

    if current:
        chunks.append(rdx.collect_text({"type": "root", "frontmatter": None, "children": current, "position": ast["position"]}))

    return chunks
```

## Development

```sh
pip install maturin
maturin develop
python -c "import rdx; print(rdx.parse('# Hello'))"
```

## License

Licensed under either of [Apache License, Version 2.0](../LICENSE-APACHE) or [MIT License](../LICENSE-MIT) at your option.
