Skip to main content

webfetch_core/
refs.rs

1//! Shared reference-style URL preservation.
2//!
3//! Both the fetch path ([`crate::convert`]) and the search path
4//! ([`crate::search`]) cite URLs with inline `[N]` markers and collect the
5//! full URLs into a trailing block. This module owns the one canonical
6//! rendering of that block so the two paths cannot drift apart.
7
8use serde::{Deserialize, Serialize};
9
10/// Anything that can be listed in a reference block: an index and a URL.
11pub trait Referable {
12    fn index(&self) -> usize;
13    fn url(&self) -> &str;
14}
15
16/// A slim reference entry (index → URL) for an output's reference block.
17#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
18pub struct Reference {
19    pub index: usize,
20    pub url: String,
21}
22
23impl Referable for Reference {
24    fn index(&self) -> usize {
25        self.index
26    }
27    fn url(&self) -> &str {
28        &self.url
29    }
30}
31
32/// Render references into the canonical block:
33///
34/// ```text
35/// References:
36/// [1] https://example.com/a
37/// [2] https://example.com/b
38/// ```
39///
40/// Returns an empty string when there are no references.
41pub fn render_block<T: Referable>(references: &[T]) -> String {
42    if references.is_empty() {
43        return String::new();
44    }
45    let mut s = String::from("References:\n");
46    for r in references {
47        s.push_str(&format!("[{}] {}\n", r.index(), r.url()));
48    }
49    s.truncate(s.trim_end().len());
50    s
51}