wme-models 0.1.3

Type definitions for the Wikimedia Enterprise API
Documentation
//! Reference and citation types.
//!
//! This module provides types for citations within article content and
//! references (bibliographic entries) that citations link to.
//!
//! # Citations vs References
//!
//! - **Citations**: Markers in the text like "\[3\]" that link to references
//! - **References**: Full bibliographic entries (books, websites, etc.)
//!
//! Citations appear in [`crate::structured::Section`] and link to
//! [`Reference`] entries in the article root.

use serde::{Deserialize, Serialize};

/// Reference/citation.
///
/// A bibliographic reference that supports claims in the article.
/// References have identifiers that link them to citations in the text.
///
/// # Reference Types
///
/// - `web` - Web-based sources
/// - `book` - Book sources
/// - `text` - Plain text (no template)
///
/// # Example
///
/// ```ignore
/// Reference {
///     identifier: "cite_note-36".to_string(),
///     group: None,
///     reference_type: ReferenceType::Web,
///     metadata: Some(json!({
///         "title": "Josephine Baker: Image & Icon",
///         "url": "http://www.jazzreview.com/...",
///     })),
///     text: ReferenceText { ... },
///     source: Some(json!({ ... })),
///     parent_reference: None,
/// }
/// ```
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
pub struct Reference {
    /// Reference identifier (links to citations)
    pub identifier: String,
    /// Reference group (for grouped references)
    pub group: Option<String>,
    /// Reference type
    #[serde(rename = "type")]
    pub reference_type: ReferenceType,
    /// Reference metadata (author, title, URL, etc.)
    pub metadata: Option<serde_json::Value>,
    /// Reference text content
    pub text: ReferenceText,
    /// Reference source information
    pub source: Option<serde_json::Value>,
    /// Parent reference identifier (for nested references)
    pub parent_reference: Option<String>,
}

/// Reference types.
///
/// The type indicates the source category based on the WikiText template
/// used to generate the reference.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum ReferenceType {
    /// Web reference (website)
    Web,
    /// Book reference
    Book,
    /// Text reference (no template)
    Text,
}

/// Reference text content.
///
/// Contains both HTML and plain text representations of the
/// formatted reference citation.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
pub struct ReferenceText {
    /// HTML representation
    pub html: Option<String>,
    /// Plain text representation
    pub plain_text: Option<String>,
}

/// Citation within content.
///
/// A citation is a marker in the text (like "\[3\]") that links to a
/// full reference entry. Citations appear in sections and link to
/// references by identifier.
///
/// # Example
///
/// ```ignore
/// Citation {
///     identifier: "cite_note-78".to_string(),
///     group: None,
///     text: Some("[78]".to_string()),
/// }
/// ```
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
pub struct Citation {
    /// Citation identifier (matches reference identifier)
    pub identifier: String,
    /// Citation text (e.g., "\[3\]")
    pub text: Option<String>,
    /// Reference identifier (same as identifier for simple citations)
    pub reference_id: Option<String>,
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_reference_creation() {
        let reference = Reference {
            identifier: "cite_note-36".to_string(),
            group: None,
            reference_type: ReferenceType::Web,
            metadata: Some(serde_json::json!({
                "title": "Example Article",
                "url": "https://example.com",
            })),
            text: ReferenceText {
                html: Some("<i>Example Article</i>".to_string()),
                plain_text: Some("Example Article".to_string()),
            },
            source: None,
            parent_reference: None,
        };

        assert_eq!(reference.identifier, "cite_note-36");
        assert!(matches!(reference.reference_type, ReferenceType::Web));
    }

    #[test]
    fn test_citation_creation() {
        let citation = Citation {
            identifier: "cite_note-78".to_string(),
            text: Some("[78]".to_string()),
            reference_id: Some("cite_note-78".to_string()),
        };

        assert_eq!(citation.identifier, "cite_note-78");
        assert_eq!(citation.text, Some("[78]".to_string()));
    }

    #[test]
    fn test_reference_types() {
        let web = ReferenceType::Web;
        let book = ReferenceType::Book;
        let text = ReferenceType::Text;

        assert!(matches!(web, ReferenceType::Web));
        assert!(matches!(book, ReferenceType::Book));
        assert!(matches!(text, ReferenceType::Text));
    }
}