Skip to main content

moss_core/resolve/
ext_kind.rs

1//! Single source of truth mapping a file extension to its embed kind.
2//! Pure; shared by build + editor. Replaces the duplication flagged at
3//! `wikilink_dispatch.rs` (synth_kind_for_ext tables vs EmbedRenderer::extensions()).
4
5use serde::{Deserialize, Serialize};
6
7/// The render family a non-folder, non-link target belongs to, by extension.
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
9#[cfg_attr(feature = "specta", derive(specta::Type))]
10pub enum ExtKind {
11    Image,
12    Iframe,
13    Pdf,
14    Video,
15    Audio,
16    Model,
17    Transclusion, // .md / .markdown
18    Notebook,     // .ipynb
19    Table,        // .csv / .tsv
20    Other,        // unknown extension → caller treats as a Link
21}
22
23/// Classify a lowercase extension (no leading dot). Unknown → `Other`.
24/// Derives from the asset registry SSOT so ext_kind and the registry never drift.
25pub fn reference_kind_for_ext(ext: &str) -> ExtKind {
26    crate::resolve::asset_registry::asset_info(ext)
27        .map(|a| a.kind)
28        .unwrap_or(ExtKind::Other)
29}
30
31#[cfg(test)]
32mod tests {
33    use super::*;
34
35    #[test]
36    fn classifies_each_family() {
37        assert_eq!(reference_kind_for_ext("png"), ExtKind::Image);
38        assert_eq!(reference_kind_for_ext("html"), ExtKind::Iframe);
39        assert_eq!(reference_kind_for_ext("pdf"), ExtKind::Pdf);
40        assert_eq!(reference_kind_for_ext("mp4"), ExtKind::Video);
41        assert_eq!(reference_kind_for_ext("mp3"), ExtKind::Audio);
42        assert_eq!(reference_kind_for_ext("glb"), ExtKind::Model);
43        assert_eq!(reference_kind_for_ext("md"), ExtKind::Transclusion);
44        assert_eq!(reference_kind_for_ext("ipynb"), ExtKind::Notebook);
45        assert_eq!(reference_kind_for_ext("csv"), ExtKind::Table);
46        assert_eq!(reference_kind_for_ext("xyz"), ExtKind::Other);
47    }
48
49    #[test]
50    fn kind_matches_registry_for_all_known_exts() {
51        use crate::resolve::asset_registry::all_assets;
52        for a in all_assets() {
53            assert_eq!(reference_kind_for_ext(a.ext), a.kind, "kind mismatch for {}", a.ext);
54        }
55        assert_eq!(reference_kind_for_ext("avif"), ExtKind::Image); // was Other before
56    }
57}