sim_codec_doc/markup/model.rs
1use std::collections::BTreeMap;
2use std::fmt;
3
4use sim_kernel::Expr;
5
6/// A semantic markup document independent of its concrete source backend.
7#[derive(Clone, Debug, PartialEq)]
8pub struct MarkupDoc {
9 /// Optional document title.
10 pub title: Option<String>,
11 /// Semantic block sequence.
12 pub blocks: Vec<MarkupBlock>,
13 /// Open document attributes carried as ordinary SIM expressions.
14 pub attrs: BTreeMap<String, Expr>,
15 /// Original source text, when a backend can preserve it.
16 pub source: Option<SourceDoc>,
17}
18
19/// A concrete source document preserved alongside the semantic IR.
20#[derive(Clone, Debug, PartialEq, Eq)]
21pub struct SourceDoc {
22 /// Backend that produced the source text.
23 pub backend: BackendId,
24 /// Verbatim source text.
25 pub text: String,
26}
27
28/// A backend identifier such as `markdown`, `typst`, `asciidoc`, or `latex`.
29#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
30pub struct BackendId(
31 /// Backend id text.
32 pub String,
33);
34
35impl BackendId {
36 /// Create a backend id from stable id text.
37 pub fn new(id: impl Into<String>) -> Self {
38 Self(id.into())
39 }
40
41 /// Borrow the backend id text.
42 pub fn as_str(&self) -> &str {
43 &self.0
44 }
45}
46
47impl fmt::Display for BackendId {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 f.write_str(&self.0)
50 }
51}
52
53/// A source span in byte offsets.
54#[derive(Clone, Debug, PartialEq, Eq)]
55pub struct Span {
56 /// Inclusive start byte offset.
57 pub start: usize,
58 /// Exclusive end byte offset.
59 pub end: usize,
60 /// Whether the semantic node still matches the original source span.
61 pub state: SpanState,
62}
63
64/// Source-span freshness after reversible document edits.
65#[derive(Clone, Debug, PartialEq, Eq)]
66pub enum SpanState {
67 /// The span still points at untouched source bytes.
68 Preserved,
69 /// The span's source bytes must be regenerated.
70 Dirty,
71}
72
73/// Markup math source with a notation label.
74#[derive(Clone, Debug, PartialEq, Eq)]
75pub struct MathSource {
76 /// Math notation, such as `tex`, `typst`, `asciimath`, or `unknown`.
77 pub notation: String,
78 /// Source text for the math expression.
79 pub text: String,
80}
81
82/// A semantic block in a markup document.
83#[derive(Clone, Debug, PartialEq)]
84pub enum MarkupBlock {
85 /// A heading with inline text.
86 Heading {
87 /// Heading level, normally 1 through 6.
88 level: u8,
89 /// Inline heading content.
90 text: Vec<Inline>,
91 /// Optional stable heading id.
92 id: Option<String>,
93 /// Optional source span.
94 span: Option<Span>,
95 },
96 /// A paragraph of inline content.
97 Paragraph {
98 /// Inline paragraph content.
99 content: Vec<Inline>,
100 /// Optional source span.
101 span: Option<Span>,
102 },
103 /// A fenced or literal code block.
104 CodeBlock {
105 /// Optional language tag.
106 lang: Option<String>,
107 /// Code text.
108 code: String,
109 /// Optional source span.
110 span: Option<Span>,
111 },
112 /// A display math block.
113 MathBlock {
114 /// Math source.
115 source: MathSource,
116 /// Optional source span.
117 span: Option<Span>,
118 },
119 /// A block quote.
120 Quote {
121 /// Quoted blocks.
122 blocks: Vec<MarkupBlock>,
123 /// Optional source span.
124 span: Option<Span>,
125 },
126 /// An ordered or unordered list.
127 List {
128 /// Whether the list is ordered.
129 ordered: bool,
130 /// List items, each item containing block content.
131 items: Vec<Vec<MarkupBlock>>,
132 /// Optional source span.
133 span: Option<Span>,
134 },
135 /// A simple table.
136 Table {
137 /// Header cells.
138 header: Vec<Vec<Inline>>,
139 /// Row cells.
140 rows: Vec<Vec<Vec<Inline>>>,
141 /// Optional source span.
142 span: Option<Span>,
143 },
144 /// A figure with source and caption.
145 Figure {
146 /// Image/media source.
147 src: String,
148 /// Figure caption.
149 caption: Vec<Inline>,
150 /// Optional source span.
151 span: Option<Span>,
152 },
153 /// Backend-specific raw text.
154 Raw {
155 /// Backend that owns the raw text.
156 backend: BackendId,
157 /// Raw source text.
158 text: String,
159 /// Optional source span.
160 span: Option<Span>,
161 },
162}
163
164/// Inline content in a markup document.
165#[derive(Clone, Debug, PartialEq, Eq)]
166pub enum Inline {
167 /// Plain text.
168 Text(String),
169 /// Emphasized inline content.
170 Emph(Vec<Inline>),
171 /// Strong inline content.
172 Strong(Vec<Inline>),
173 /// Inline code.
174 Code(String),
175 /// Link with label and target.
176 Link {
177 /// Link label.
178 label: Vec<Inline>,
179 /// Link target.
180 target: String,
181 },
182 /// Inline math.
183 Math(MathSource),
184 /// Backend-specific raw inline text.
185 Raw {
186 /// Backend that owns the raw text.
187 backend: BackendId,
188 /// Raw source text.
189 text: String,
190 },
191}