Skip to main content

mdcast_client/
request.rs

1//! Constructors for the two wire request bodies.
2//!
3//! [`RenderMarkdownRequest`] and [`RenderTemplateRequest`] are plain serde
4//! structs in `mdcast-api` with no `Default` (markdown and target are not
5//! optional), so building one by hand means naming every field. These give the
6//! common case one expression; everything else is a struct-update:
7//!
8//! ```
9//! use mdcast_client::request;
10//! use mdcast_api::{Target, wire::RenderOptions};
11//!
12//! let mut req = request::markdown("# Q3", Target::Pdf);
13//! req.options = RenderOptions {
14//!     mermaid: true,
15//!     toc_depth: Some(2),
16//!     ..RenderOptions::default()
17//! };
18//! ```
19//!
20//! The `assets` manifest is deliberately left empty: the client fills it from
21//! the [`crate::AssetBundle`] handed to the render call.
22
23use mdcast_api::wire::{RenderMarkdownRequest, RenderTemplateRequest};
24use mdcast_api::{AssetManifest, DocMeta, Target};
25
26/// Render `markdown` to `target`, with no brand and no options.
27pub fn markdown(markdown: impl Into<String>, target: Target) -> RenderMarkdownRequest {
28    RenderMarkdownRequest {
29        markdown: markdown.into(),
30        meta: DocMeta::default(),
31        brand: None,
32        target,
33        assets: AssetManifest::new(),
34        options: Default::default(),
35    }
36}
37
38/// Render a typst template over `data` (raw JSON text, the bytes that become
39/// the virtual `/data.json`) to PDF.
40pub fn template(
41    template_source: impl Into<String>,
42    data: impl Into<String>,
43) -> RenderTemplateRequest {
44    RenderTemplateRequest {
45        template_source: template_source.into(),
46        data: data.into(),
47        meta: DocMeta::default(),
48        brand: None,
49        format: Default::default(),
50        assets: AssetManifest::new(),
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57    use mdcast_api::wire::{RenderOptions, TemplateFormat};
58
59    #[test]
60    fn markdown_defaults_everything_but_the_body_and_target() {
61        let req = markdown("# Hi", Target::HtmlReveal);
62
63        assert_eq!(req.markdown, "# Hi");
64        assert_eq!(req.target, Target::HtmlReveal);
65        assert_eq!(req.meta, DocMeta::default());
66        assert_eq!(req.brand, None);
67        assert_eq!(req.options, RenderOptions::default());
68        assert!(
69            req.assets.is_empty(),
70            "the bundle fills the manifest, not the caller"
71        );
72    }
73
74    #[test]
75    fn template_defaults_to_pdf() {
76        let req = template("= Invoice", r#"{"number":"INV-042"}"#);
77
78        assert_eq!(req.format, TemplateFormat::Pdf);
79        assert_eq!(req.data, r#"{"number":"INV-042"}"#);
80        assert!(req.assets.is_empty());
81    }
82}