wme_models/reference.rs
1//! Reference and citation types.
2//!
3//! This module provides types for citations within article content and
4//! references (bibliographic entries) that citations link to.
5//!
6//! # Citations vs References
7//!
8//! - **Citations**: Markers in the text like "\[3\]" that link to references
9//! - **References**: Full bibliographic entries (books, websites, etc.)
10//!
11//! Citations appear in [`crate::structured::Section`] and link to
12//! [`Reference`] entries in the article root.
13
14use serde::{Deserialize, Serialize};
15
16/// Reference/citation.
17///
18/// A bibliographic reference that supports claims in the article.
19/// References have identifiers that link them to citations in the text.
20///
21/// # Reference Types
22///
23/// - `web` - Web-based sources
24/// - `book` - Book sources
25/// - `text` - Plain text (no template)
26///
27/// # Example
28///
29/// ```ignore
30/// Reference {
31/// identifier: "cite_note-36".to_string(),
32/// group: None,
33/// reference_type: ReferenceType::Web,
34/// metadata: Some(json!({
35/// "title": "Josephine Baker: Image & Icon",
36/// "url": "http://www.jazzreview.com/...",
37/// })),
38/// text: ReferenceText { ... },
39/// source: Some(json!({ ... })),
40/// parent_reference: None,
41/// }
42/// ```
43#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
44pub struct Reference {
45 /// Reference identifier (links to citations)
46 pub identifier: String,
47 /// Reference group (for grouped references)
48 pub group: Option<String>,
49 /// Reference type
50 #[serde(rename = "type")]
51 pub reference_type: ReferenceType,
52 /// Reference metadata (author, title, URL, etc.)
53 pub metadata: Option<serde_json::Value>,
54 /// Reference text content
55 pub text: ReferenceText,
56 /// Reference source information
57 pub source: Option<serde_json::Value>,
58 /// Parent reference identifier (for nested references)
59 pub parent_reference: Option<String>,
60}
61
62/// Reference types.
63///
64/// The type indicates the source category based on the WikiText template
65/// used to generate the reference.
66#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
67#[serde(rename_all = "snake_case")]
68pub enum ReferenceType {
69 /// Web reference (website)
70 Web,
71 /// Book reference
72 Book,
73 /// Text reference (no template)
74 Text,
75}
76
77/// Reference text content.
78///
79/// Contains both HTML and plain text representations of the
80/// formatted reference citation.
81#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
82pub struct ReferenceText {
83 /// HTML representation
84 pub html: Option<String>,
85 /// Plain text representation
86 pub plain_text: Option<String>,
87}
88
89/// Citation within content.
90///
91/// A citation is a marker in the text (like "\[3\]") that links to a
92/// full reference entry. Citations appear in sections and link to
93/// references by identifier.
94///
95/// # Example
96///
97/// ```ignore
98/// Citation {
99/// identifier: "cite_note-78".to_string(),
100/// group: None,
101/// text: Some("[78]".to_string()),
102/// }
103/// ```
104#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
105pub struct Citation {
106 /// Citation identifier (matches reference identifier)
107 pub identifier: String,
108 /// Citation text (e.g., "\[3\]")
109 pub text: Option<String>,
110 /// Reference identifier (same as identifier for simple citations)
111 pub reference_id: Option<String>,
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117
118 #[test]
119 fn test_reference_creation() {
120 let reference = Reference {
121 identifier: "cite_note-36".to_string(),
122 group: None,
123 reference_type: ReferenceType::Web,
124 metadata: Some(serde_json::json!({
125 "title": "Example Article",
126 "url": "https://example.com",
127 })),
128 text: ReferenceText {
129 html: Some("<i>Example Article</i>".to_string()),
130 plain_text: Some("Example Article".to_string()),
131 },
132 source: None,
133 parent_reference: None,
134 };
135
136 assert_eq!(reference.identifier, "cite_note-36");
137 assert!(matches!(reference.reference_type, ReferenceType::Web));
138 }
139
140 #[test]
141 fn test_citation_creation() {
142 let citation = Citation {
143 identifier: "cite_note-78".to_string(),
144 text: Some("[78]".to_string()),
145 reference_id: Some("cite_note-78".to_string()),
146 };
147
148 assert_eq!(citation.identifier, "cite_note-78");
149 assert_eq!(citation.text, Some("[78]".to_string()));
150 }
151
152 #[test]
153 fn test_reference_types() {
154 let web = ReferenceType::Web;
155 let book = ReferenceType::Book;
156 let text = ReferenceType::Text;
157
158 assert!(matches!(web, ReferenceType::Web));
159 assert!(matches!(book, ReferenceType::Book));
160 assert!(matches!(text, ReferenceType::Text));
161 }
162}