unifast-bindings-node 0.0.10

High-performance Markdown/MDX compiler
Documentation
use napi_derive::napi;
use unifast_core::api::result::{CompileResult, Output};
use unifast_core::diagnostics::diagnostic::DiagLevel;

#[napi(object)]
pub struct JsDiagnostic {
    pub level: String,
    pub message: String,
    pub start: Option<u32>,
    pub end: Option<u32>,
}

#[napi(object)]
pub struct JsCompileStats {
    pub parse_ms: f64,
    pub transform_ms: f64,
    pub emit_ms: f64,
}

#[napi(object)]
pub struct JsTocEntry {
    pub depth: u32,
    pub text: String,
    pub slug: String,
}

#[napi(object)]
pub struct JsReadingTime {
    pub words: u32,
    pub minutes: f64,
}

#[napi(object)]
pub struct JsCompileResult {
    pub output: String,
    pub sourcemap: Option<String>,
    pub frontmatter: String,
    pub diagnostics: Vec<JsDiagnostic>,
    pub stats: JsCompileStats,
    pub toc: Vec<JsTocEntry>,
    pub reading_time: Option<JsReadingTime>,
    pub excerpt: Option<String>,
}

pub fn convert_result(result: CompileResult) -> JsCompileResult {
    let (output, sourcemap) = match result.output {
        Output::Html(html) => (html, None),
        Output::MdxJs { code, map } => (code, map),
        Output::Hast(ref root) => (
            serde_json::to_string(root).unwrap_or_else(|e| format!("{{\"error\":\"{e}\"}}")),
            None,
        ),
        Output::Mdast(ref doc) => (
            serde_json::to_string(doc).unwrap_or_else(|e| format!("{{\"error\":\"{e}\"}}")),
            None,
        ),
    };

    JsCompileResult {
        output,
        sourcemap,
        frontmatter: serde_json::to_string(&result.frontmatter)
            .unwrap_or_else(|_| "{}".to_string()),
        diagnostics: result
            .diagnostics
            .into_iter()
            .map(|d| JsDiagnostic {
                level: match d.level {
                    DiagLevel::Error => "error".to_string(),
                    DiagLevel::Warning => "warn".to_string(),
                },
                start: Some(d.span.start),
                end: Some(d.span.end),
                message: d.message,
            })
            .collect(),
        stats: JsCompileStats {
            parse_ms: result.stats.parse_ms,
            transform_ms: result.stats.transform_ms,
            emit_ms: result.stats.emit_ms,
        },
        toc: result
            .toc
            .into_iter()
            .map(|e| JsTocEntry {
                depth: u32::from(e.depth),
                text: e.text,
                slug: e.slug,
            })
            .collect(),
        reading_time: result.reading_time.map(|rt| JsReadingTime {
            words: rt.words,
            minutes: rt.minutes,
        }),
        excerpt: result.excerpt,
    }
}