Skip to main content

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}