Skip to main content

acdc_parser/model/inlines/
text.rs

1use serde::{
2    Serialize,
3    ser::{SerializeMap, Serializer},
4};
5
6use crate::{Location, Role, Substitution};
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    /// The substitutions to apply when rendering this node.
159    ///
160    /// Carries the passthrough's own substitution list (minus Quotes, which are
161    /// already handled during parsing). The converter uses these subs directly
162    /// instead of the enclosing block's substitutions. An empty vec means no
163    /// substitutions (raw output), as with `+++text+++` and `pass:[text]`.
164    pub subs: Vec<Substitution>,
165}
166
167/// A `Verbatim` represents verbatim text section in a document.
168///
169/// This is the most basic form of text in a document and it should note that its contents
170/// must be rendered as they are (e.g: "\<h1>" should not end up being a \<h1> tag, it
171/// should be "\<h1>" text in html, very likely \&lt;h1\&gt;).
172///
173/// It is similar to `Raw`, but is intended for use in contexts where verbatim text is
174/// used, and some substitutions are done, namely converting callouts.
175#[derive(Clone, Debug, PartialEq)]
176pub struct Verbatim {
177    pub content: String,
178    pub location: Location,
179}
180
181impl Serialize for StandaloneCurvedApostrophe {
182    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
183    where
184        S: Serializer,
185    {
186        let mut state = serializer.serialize_map(Some(3))?;
187        state.serialize_entry("name", "curved_apostrophe")?;
188        state.serialize_entry("type", "string")?;
189        state.serialize_entry("location", &self.location)?;
190        state.end()
191    }
192}
193
194/// The kind of callout reference marker (how it was expressed in the source).
195#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
196#[serde(rename_all = "lowercase")]
197pub enum CalloutRefKind {
198    /// Explicit callout: `<1>`, `<2>`, etc. - the number was specified directly.
199    Explicit,
200    /// Auto-numbered callout: `<.>` - the number was resolved automatically.
201    Auto,
202}
203
204/// A `CalloutRef` represents a callout reference marker within verbatim content.
205///
206/// Callout references appear at the end of lines in source/listing blocks and
207/// link to explanatory text in a subsequent callout list.
208///
209/// # Examples
210///
211/// ```asciidoc
212/// [source,ruby]
213/// ----
214/// def main <1>
215///   puts 'hello' <.>
216/// end
217/// ----
218/// <1> Defines the main function
219/// <.> Prints a greeting
220/// ```
221///
222/// The `<1>` marker creates an `Explicit` callout ref, while `<.>` creates an
223/// `Auto` callout ref that gets resolved to the next available number.
224#[derive(Clone, Debug, PartialEq, Eq)]
225pub struct CalloutRef {
226    /// The kind of callout (explicit number vs auto-numbered).
227    pub kind: CalloutRefKind,
228    /// The resolved callout number (1-indexed).
229    pub number: usize,
230    /// Source location of this callout reference.
231    pub location: Location,
232}
233
234impl CalloutRef {
235    /// Creates a new explicit callout reference with the given number.
236    #[must_use]
237    pub fn explicit(number: usize, location: Location) -> Self {
238        Self {
239            kind: CalloutRefKind::Explicit,
240            number,
241            location,
242        }
243    }
244
245    /// Creates a new auto-numbered callout reference with the resolved number.
246    #[must_use]
247    pub fn auto(number: usize, location: Location) -> Self {
248        Self {
249            kind: CalloutRefKind::Auto,
250            number,
251            location,
252        }
253    }
254}
255
256impl Serialize for CalloutRef {
257    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
258    where
259        S: Serializer,
260    {
261        let mut state = serializer.serialize_map(Some(5))?;
262        state.serialize_entry("name", "callout_reference")?;
263        state.serialize_entry("type", "inline")?;
264        state.serialize_entry("variant", &self.kind)?;
265        state.serialize_entry("number", &self.number)?;
266        state.serialize_entry("location", &self.location)?;
267        state.end()
268    }
269}