use pyo3::prelude::*;
use pyo3::types::PyDict;
use crate::Document as RustDocument;
#[pyclass(name = "Document")]
#[derive(Clone)]
pub struct PyDocument {
inner: RustDocument,
}
#[pymethods]
impl PyDocument {
#[staticmethod]
fn parse(markdown: &str) -> PyResult<Self> {
Ok(PyDocument {
inner: RustDocument::parse(markdown),
})
}
#[staticmethod]
fn to_html(markdown: &str) -> PyResult<String> {
Ok(RustDocument::to_html(markdown))
}
#[getter]
fn html(&self) -> PyResult<String> {
Ok(self.inner.html.clone())
}
#[getter]
fn metadata(&self, py: Python) -> PyResult<PyObject> {
let dict = PyDict::new(py);
for (key, value) in &self.inner.metadata {
dict.set_item(key, value)?;
}
Ok(dict.into())
}
#[getter]
fn toc(&self) -> PyResult<String> {
Ok(self.inner.toc.clone())
}
#[getter]
fn reading_time(&self) -> PyResult<usize> {
Ok(self.inner.reading_time)
}
#[getter]
fn headings(&self) -> PyResult<Vec<PyHeading>> {
Ok(self
.inner
.headings
.iter()
.map(|h| PyHeading {
text: h.text.clone(),
level: h.level,
id: h.id.clone(),
})
.collect())
}
fn __repr__(&self) -> String {
format!(
"Document(headings={}, reading_time={}min)",
self.inner.headings.len(),
self.inner.reading_time
)
}
fn __str__(&self) -> String {
self.inner.html.clone()
}
}
#[pyclass(name = "Heading")]
#[derive(Clone)]
pub struct PyHeading {
#[pyo3(get)]
pub text: String,
#[pyo3(get)]
pub level: usize,
#[pyo3(get)]
pub id: String,
}
#[pymethods]
impl PyHeading {
fn __repr__(&self) -> String {
format!(
"Heading(text='{}', level={}, id='{}')",
self.text, self.level, self.id
)
}
fn __str__(&self) -> String {
self.text.clone()
}
}
#[pymodule]
fn mdja(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<PyDocument>()?;
m.add_class::<PyHeading>()?;
m.add(
"__doc__",
"日本語に最適化されたMarkdownパーサー\n\n\
Features:\n\
- CommonMark + GFM support\n\
- Japanese heading anchor generation\n\
- Table of contents generation\n\
- Reading time calculation\n\
- Frontmatter parsing\n\n\
Example:\n\
>>> import mdja\n\
>>> doc = mdja.Document.parse('# Hello\\n\\nWorld')\n\
>>> print(doc.html)\n\
>>> print(f'Reading time: {doc.reading_time} min')\n\
",
)?;
m.add("__version__", env!("CARGO_PKG_VERSION"))?;
Ok(())
}