mos_eval/inline.rs
1//! Lower inline parser nodes into semantic document children.
2
3use std::collections::BTreeMap;
4
5use mos_core::{AttrMap, AttrValue, Document, NodeId, NodeKind, NodeSpec};
6use mos_parse::{Inline, InlineKind};
7
8use crate::insert_label_attributes;
9
10pub(super) fn lower_inlines(doc: &mut Document, parent: NodeId, inlines: &[Inline]) {
11 for inline in inlines {
12 let kind = match inline.kind {
13 InlineKind::Text => NodeKind::Text,
14 InlineKind::Emphasis => NodeKind::Emphasis,
15 InlineKind::Strong => NodeKind::Strong,
16 InlineKind::BoldItalic => NodeKind::BoldItalic,
17 InlineKind::Code => NodeKind::Raw,
18 InlineKind::Reference => NodeKind::Reference,
19 InlineKind::PageReference => NodeKind::PageReference,
20 InlineKind::Citation => NodeKind::Citation,
21 InlineKind::HardBreak => NodeKind::HardBreak,
22 };
23 let mut attributes: AttrMap = BTreeMap::new();
24 match inline.kind {
25 InlineKind::Reference => {
26 // Stamp the label and its identifier `label_span` (issue #116)
27 // exactly as declarations are, so rename reads the editable
28 // identifier range directly instead of re-deriving it from the
29 // reference node's span geometry. Pre-resolve placeholder text:
30 // the resolver overwrites it on success; unresolved refs still
31 // render visible `?label?` text.
32 insert_label_attributes(&mut attributes, &inline.text, inline.label_span.as_ref());
33 attributes.insert(
34 "text".to_owned(),
35 AttrValue::Str(format!("?{}?", inline.text)),
36 );
37 }
38 InlineKind::PageReference => {
39 // Same label + identifier-span stamp as a cross-reference
40 // (issue #116). The `?label?` placeholder stays visible until
41 // the resolve↔layout fixpoint (issue #72) rewrites it to the
42 // target's page number; this slice models the node only.
43 insert_label_attributes(&mut attributes, &inline.text, inline.label_span.as_ref());
44 attributes.insert(
45 "text".to_owned(),
46 AttrValue::Str(format!("?{}?", inline.text)),
47 );
48 }
49 InlineKind::Citation => {
50 // Record the bare key and a visible `[?key?]` fallback.
51 // `resolve_citations` rewrites this to a numeric label
52 // (`[1]`, ...) for keys found in a declared bibliography;
53 // unresolved keys keep `[?key?]` so the citation stays
54 // visible the same way unresolved refs are.
55 attributes.insert("key".to_owned(), AttrValue::Str(inline.text.clone()));
56 attributes.insert(
57 "text".to_owned(),
58 AttrValue::Str(format!("[?{}?]", inline.text)),
59 );
60 }
61 // Hard breaks are pure structural markers -- no text payload
62 // to lower, no attributes. Layout's `collect_words` matches
63 // on `NodeKind::HardBreak` directly.
64 InlineKind::HardBreak => {}
65 _ => {
66 attributes.insert("text".to_owned(), AttrValue::Str(inline.text.clone()));
67 }
68 }
69 doc.alloc_child(
70 parent,
71 NodeSpec::new(kind, inline.span.clone()).with_attributes(attributes),
72 );
73 }
74}