use crate::store::node::NodeKind;
use crate::scrivener::binder::BinderItem;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Classification {
UserBook,
Chapter,
Subchapter,
Paragraph,
SystemBook(&'static str),
SkipKeepChildren,
SkipSubtree,
}
pub fn classify(
item: &BinderItem,
depth_in_draft: Option<usize>,
) -> Classification {
if let Some(depth) = depth_in_draft {
return match (item.kind.as_str(), depth) {
("DraftFolder", 0) => Classification::UserBook,
("Folder", 1) => Classification::Chapter,
("Folder", _) => Classification::Subchapter,
("Text", _) => Classification::Paragraph,
(_, _) => Classification::Subchapter,
};
}
let title_lower = item.title.to_ascii_lowercase();
let known_bucket = match title_lower.as_str() {
"places" | "locations" | "settings" => Some("places"),
"characters" | "cast" => Some("characters"),
"notes" => Some("notes"),
"research" => Some("notes"), "artefacts" | "artifacts" | "items" => Some("artefacts"),
_ => None,
};
if let Some(tag) = known_bucket {
return Classification::SystemBook(tag);
}
if item.kind == "Folder" {
Classification::SkipKeepChildren
} else {
Classification::SkipSubtree
}
}
pub fn node_kind_for(c: &Classification) -> Option<NodeKind> {
match c {
Classification::UserBook | Classification::SystemBook(_) => {
Some(NodeKind::Book)
}
Classification::Chapter => Some(NodeKind::Chapter),
Classification::Subchapter => Some(NodeKind::Subchapter),
Classification::Paragraph => Some(NodeKind::Paragraph),
Classification::SkipKeepChildren | Classification::SkipSubtree => None,
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::scrivener::binder::BinderItem;
use uuid::Uuid;
fn item(kind: &str, title: &str) -> BinderItem {
BinderItem {
uuid: Uuid::nil(),
kind: kind.into(),
title: title.into(),
children: Vec::new(),
}
}
#[test]
fn draft_root_is_user_book() {
let i = item("DraftFolder", "Manuscript");
assert_eq!(classify(&i, Some(0)), Classification::UserBook);
}
#[test]
fn folder_depth_drives_chapter_vs_subchapter() {
let i = item("Folder", "Chapter 1");
assert_eq!(classify(&i, Some(1)), Classification::Chapter);
assert_eq!(classify(&i, Some(2)), Classification::Subchapter);
assert_eq!(classify(&i, Some(3)), Classification::Subchapter);
}
#[test]
fn text_is_always_paragraph_inside_draft() {
let i = item("Text", "The Storm");
assert_eq!(classify(&i, Some(2)), Classification::Paragraph);
}
#[test]
fn outside_draft_known_folders_route() {
let i = item("Folder", "Characters");
assert_eq!(
classify(&i, None),
Classification::SystemBook("characters")
);
let i = item("Folder", "Research");
assert_eq!(classify(&i, None), Classification::SystemBook("notes"));
}
#[test]
fn outside_draft_unknown_folder_keeps_children() {
let i = item("Folder", "Reference Materials");
assert_eq!(classify(&i, None), Classification::SkipKeepChildren);
}
}