dmc_transform/config.rs
1//! Pipeline-level configuration. Compiled unconditionally so callers can
2//! describe the pipeline (themes, copy-linked-files paths, gfm switch, ...)
3//! whether or not the matching feature flags are enabled.
4//!
5//! When a config field describes a transformer whose feature is off,
6//! [`Pipeline::with_defaults_for`](crate::Pipeline::with_defaults_for)
7//! silently skips it -- the field is still allowed in the config so user
8//! settings round-trip cleanly across builds with different feature sets.
9
10use serde::{Deserialize, Serialize};
11use std::collections::BTreeMap;
12use std::path::PathBuf;
13
14/// Top-level config consumed by [`Pipeline::with_defaults_for`].
15/// All fields are optional; the empty config (`PipelineConfig::default()`)
16/// reproduces the historical `Pipeline::with_defaults()` behavior.
17#[derive(Debug, Clone, Default, Serialize, Deserialize)]
18#[serde(default)]
19pub struct PipelineConfig {
20 /// When `false`, append the `disable-gfm` transformer that strips GFM
21 /// extensions (tables, strikethrough, autolinks, task lists).
22 pub markdown_gfm: Option<bool>,
23 /// Pretty-code theme + multi-mode settings. `None` keeps the bundled
24 /// defaults (Catppuccin Latte/Mocha pair, dark primary).
25 pub pretty_code: Option<PrettyCodeOptions>,
26 /// LaTeX rendering engine. `None` -> [`MathEngine::Katex`].
27 pub math_engine: Option<MathEngine>,
28 /// When `Some`, append the `copy-linked-files` transformer with the
29 /// supplied paths.
30 pub copy_linked_files: Option<CopyLinkedFilesOptions>,
31}
32
33/// Which engine renders `$...$` / `$$...$$` math.
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
35#[serde(rename_all = "lowercase")]
36pub enum MathEngine {
37 /// Embedded KaTeX via `quick-js`. Output matches `rehype-katex` byte
38 /// for byte. Slow per-expression (1-5 ms each).
39 #[default]
40 Katex,
41 /// `pulldown-latex` -> MathML. Fast (microseconds). Browser MathML
42 /// rendering is functional but visually plainer than KaTeX HTML.
43 Mathml,
44}
45
46/// Pretty-code theme spec.
47///
48/// Deserialised untagged: pass a JSON string for single-theme, or an
49/// object `{ light: "...", dark: "...", ... }` for multi-mode output.
50#[derive(Debug, Clone, Serialize, Deserialize)]
51#[serde(untagged)]
52pub enum PrettyCodeTheme {
53 /// Single bundled theme name. Emits per-token `style="color:#xxx"`.
54 Single(String),
55 /// Map of `mode -> bundled theme name`. Mode keys are arbitrary
56 /// (`light`, `dark`, `dim`, ...); they appear in the emitted CSS as
57 /// `--dmc-{mode}` / `--dmc-{mode}-bg` CSS custom properties.
58 Multi(BTreeMap<String, String>),
59}
60
61impl Default for PrettyCodeTheme {
62 fn default() -> Self {
63 Self::Multi(
64 [("light".to_string(), "Catppuccin Latte".to_string()), ("dark".to_string(), "Catppuccin Mocha".to_string())]
65 .into_iter()
66 .collect(),
67 )
68 }
69}
70
71/// Top-level pretty-code configuration. Stored on `CompileConfig` as
72/// `Option<PrettyCodeOptions>`; `None` means "use built-in defaults".
73#[derive(Debug, Clone, Default, Serialize, Deserialize)]
74#[serde(default)]
75pub struct PrettyCodeOptions {
76 /// Theme spec. String for single-theme, object for multi-mode.
77 pub theme: PrettyCodeTheme,
78 /// Mode key whose colors fill the unprefixed `color` /
79 /// `background-color` attrs. Only meaningful for [`PrettyCodeTheme::Multi`].
80 /// When unset, resolves to `"dark"` if present, else the first key.
81 pub default_mode: Option<String>,
82}
83
84/// Paths consumed by the `copy-linked-files` transformer.
85#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct CopyLinkedFilesOptions {
87 /// Directory the source `.mdx` lives in -- used to resolve relative
88 /// `src` / `href` attrs.
89 pub source_dir: PathBuf,
90 /// Output asset directory (where copies are written).
91 pub assets_dir: PathBuf,
92 /// Public URL prefix prepended to rewritten asset paths.
93 pub public_base: String,
94}