Skip to main content

acdc_parser/model/inlines/
text.rs

1use serde::{
2    Serialize,
3    ser::{SerializeMap, Serializer},
4};
5
6use crate::{Location, Role};
7
8use super::InlineNode;
9
10/// The form of an inline formatting element (how it was expressed in the source)
11#[derive(Clone, Debug, PartialEq, Serialize)]
12#[serde(rename_all = "lowercase")]
13pub enum Form {
14    Constrained,
15    Unconstrained,
16}
17
18/// A `Subscript` represents a subscript section of text in a document.
19#[derive(Clone, Debug, PartialEq)]
20pub struct Subscript {
21    pub role: Option<Role>,
22    pub id: Option<String>,
23    pub form: Form,
24    pub content: Vec<InlineNode>,
25    pub location: Location,
26}
27
28/// A `Superscript` represents a superscript section of text in a document.
29#[derive(Clone, Debug, PartialEq)]
30pub struct Superscript {
31    pub role: Option<Role>,
32    pub id: Option<String>,
33    pub form: Form,
34    pub content: Vec<InlineNode>,
35    pub location: Location,
36}
37
38/// A `CurvedQuotation` represents a curved quotation section of text in a document.
39#[derive(Clone, Debug, PartialEq)]
40pub struct CurvedQuotation {
41    pub role: Option<Role>,
42    pub id: Option<String>,
43    pub form: Form,
44    pub content: Vec<InlineNode>,
45    pub location: Location,
46}
47
48/// A `CurvedApostrophe` represents a curved apostrophe section of text in a document.
49#[derive(Clone, Debug, PartialEq)]
50pub struct CurvedApostrophe {
51    pub role: Option<Role>,
52    pub id: Option<String>,
53    pub form: Form,
54    pub content: Vec<InlineNode>,
55    pub location: Location,
56}
57
58/// A `StandaloneCurvedApostrophe` represents a standalone curved apostrophe character.
59#[derive(Clone, Debug, PartialEq)]
60pub struct StandaloneCurvedApostrophe {
61    pub location: Location,
62}
63
64/// A `Monospace` represents a monospace section of text in a document.
65#[derive(Clone, Debug, PartialEq)]
66pub struct Monospace {
67    pub role: Option<Role>,
68    pub id: Option<String>,
69    pub form: Form,
70    pub content: Vec<InlineNode>,
71    pub location: Location,
72}
73
74/// A `Highlight` represents a highlighted section of text in a document.
75#[derive(Clone, Debug, PartialEq)]
76pub struct Highlight {
77    pub role: Option<Role>,
78    pub id: Option<String>,
79    pub form: Form,
80    pub content: Vec<InlineNode>,
81    pub location: Location,
82}
83
84/// A `Bold` represents a bold section of text in a document.
85#[derive(Clone, Debug, PartialEq)]
86pub struct Bold {
87    pub role: Option<Role>,
88    pub id: Option<String>,
89    pub form: Form,
90    pub content: Vec<InlineNode>,
91    pub location: Location,
92}
93
94/// An `Italic` represents an italic section of text in a document.
95#[derive(Clone, Debug, PartialEq)]
96pub struct Italic {
97    pub role: Option<Role>,
98    pub id: Option<String>,
99    pub form: Form,
100    pub content: Vec<InlineNode>,
101    pub location: Location,
102}
103
104/// A `LineBreak` represents a line break (inline).
105#[derive(Clone, Debug, PartialEq)]
106pub struct LineBreak {
107    pub location: Location,
108}
109
110impl Serialize for LineBreak {
111    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
112    where
113        S: Serializer,
114    {
115        let mut state = serializer.serialize_map(Some(3))?;
116        state.serialize_entry("name", "linebreak")?;
117        state.serialize_entry("type", "string")?;
118        state.serialize_entry("location", &self.location)?;
119        state.end()
120    }
121}
122
123/// A `Plain` represents a plain text section in a document.
124///
125/// This is the most basic form of text in a document.
126#[derive(Clone, Debug, PartialEq)]
127pub struct Plain {
128    pub content: String,
129    pub location: Location,
130    /// True if content originated from an escaped pattern (e.g., `\^2^`).
131    /// When true, the converter should not re-parse for quotes.
132    pub escaped: bool,
133}
134
135impl Serialize for Plain {
136    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
137    where
138        S: Serializer,
139    {
140        let mut state = serializer.serialize_map(Some(4))?;
141        state.serialize_entry("name", "text")?;
142        state.serialize_entry("type", "string")?;
143        state.serialize_entry("value", &self.content)?;
144        state.serialize_entry("location", &self.location)?;
145        state.end()
146    }
147}
148
149/// A `Raw` represents a raw text section in a document.
150///
151/// This is the most basic form of text in a document and it should note that its contents
152/// must be rendered as they are (e.g: "\<h1>" should not end up being a \<h1> tag, it
153/// should be "\<h1>" text in html, very likely \&lt;h1\&gt;).
154#[derive(Clone, Debug, PartialEq)]
155pub struct Raw {
156    pub content: String,
157    pub location: Location,
158}
159
160/// A `Verbatim` represents verbatim text section in a document.
161///
162/// This is the most basic form of text in a document and it should note that its contents
163/// must be rendered as they are (e.g: "\<h1>" should not end up being a \<h1> tag, it
164/// should be "\<h1>" text in html, very likely \&lt;h1\&gt;).
165///
166/// It is similar to `Raw`, but is intended for use in contexts where verbatim text is
167/// used, and some substitutions are done, namely converting callouts.
168#[derive(Clone, Debug, PartialEq)]
169pub struct Verbatim {
170    pub content: String,
171    pub location: Location,
172}
173
174impl Serialize for StandaloneCurvedApostrophe {
175    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
176    where
177        S: Serializer,
178    {
179        let mut state = serializer.serialize_map(Some(3))?;
180        state.serialize_entry("name", "curved_apostrophe")?;
181        state.serialize_entry("type", "string")?;
182        state.serialize_entry("location", &self.location)?;
183        state.end()
184    }
185}
186
187/// The kind of callout reference marker (how it was expressed in the source).
188#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
189#[serde(rename_all = "lowercase")]
190pub enum CalloutRefKind {
191    /// Explicit callout: `<1>`, `<2>`, etc. - the number was specified directly.
192    Explicit,
193    /// Auto-numbered callout: `<.>` - the number was resolved automatically.
194    Auto,
195}
196
197/// A `CalloutRef` represents a callout reference marker within verbatim content.
198///
199/// Callout references appear at the end of lines in source/listing blocks and
200/// link to explanatory text in a subsequent callout list.
201///
202/// # Examples
203///
204/// ```asciidoc
205/// [source,ruby]
206/// ----
207/// def main <1>
208///   puts 'hello' <.>
209/// end
210/// ----
211/// <1> Defines the main function
212/// <.> Prints a greeting
213/// ```
214///
215/// The `<1>` marker creates an `Explicit` callout ref, while `<.>` creates an
216/// `Auto` callout ref that gets resolved to the next available number.
217#[derive(Clone, Debug, PartialEq, Eq)]
218pub struct CalloutRef {
219    /// The kind of callout (explicit number vs auto-numbered).
220    pub kind: CalloutRefKind,
221    /// The resolved callout number (1-indexed).
222    pub number: usize,
223    /// Source location of this callout reference.
224    pub location: Location,
225}
226
227impl CalloutRef {
228    /// Creates a new explicit callout reference with the given number.
229    #[must_use]
230    pub fn explicit(number: usize, location: Location) -> Self {
231        Self {
232            kind: CalloutRefKind::Explicit,
233            number,
234            location,
235        }
236    }
237
238    /// Creates a new auto-numbered callout reference with the resolved number.
239    #[must_use]
240    pub fn auto(number: usize, location: Location) -> Self {
241        Self {
242            kind: CalloutRefKind::Auto,
243            number,
244            location,
245        }
246    }
247}
248
249impl Serialize for CalloutRef {
250    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
251    where
252        S: Serializer,
253    {
254        let mut state = serializer.serialize_map(Some(5))?;
255        state.serialize_entry("name", "callout_reference")?;
256        state.serialize_entry("type", "inline")?;
257        state.serialize_entry("variant", &self.kind)?;
258        state.serialize_entry("number", &self.number)?;
259        state.serialize_entry("location", &self.location)?;
260        state.end()
261    }
262}