Skip to content

Commit d316d96

Browse files
committed
feat: Allow all titles to have IDs
1 parent c933180 commit d316d96

File tree

4 files changed

+56
-16
lines changed

4 files changed

+56
-16
lines changed

src/level.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@ impl<'a> Level<'a> {
7474
/// </div>
7575
pub fn header(self, header: &'a str) -> Message<'a> {
7676
Message {
77-
id: None,
7877
groups: vec![Group::new().element(Element::Title(Title {
7978
level: self,
79+
id: None,
8080
title: header,
8181
is_pre_styled: false,
8282
}))],
@@ -93,6 +93,7 @@ impl<'a> Level<'a> {
9393
pub fn title(self, title: &'a str) -> Title<'a> {
9494
Title {
9595
level: self,
96+
id: None,
9697
title,
9798
is_pre_styled: false,
9899
}
@@ -109,6 +110,7 @@ impl<'a> Level<'a> {
109110
pub fn pre_styled_title(self, title: &'a str) -> Title<'a> {
110111
Title {
111112
level: self,
113+
id: None,
112114
title,
113115
is_pre_styled: true,
114116
}

src/renderer/mod.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -338,13 +338,6 @@ impl Renderer {
338338
title,
339339
max_line_num_len,
340340
title_style,
341-
message.id.as_ref().and_then(|id| {
342-
if g == 0 && i == 0 {
343-
Some(id)
344-
} else {
345-
None
346-
}
347-
}),
348341
matches!(peek, Some(Element::Title(_))),
349342
buffer_msg_line_offset,
350343
);
@@ -524,7 +517,6 @@ impl Renderer {
524517
&title,
525518
0, // No line numbers in short messages
526519
TitleStyle::MainHeader,
527-
message.id.as_ref(),
528520
false,
529521
0,
530522
);
@@ -546,7 +538,6 @@ impl Renderer {
546538
title: &Title<'_>,
547539
max_line_num_len: usize,
548540
title_style: TitleStyle,
549-
id: Option<&Id<'_>>,
550541
is_cont: bool,
551542
buffer_msg_line_offset: usize,
552543
) {
@@ -582,7 +573,7 @@ impl Renderer {
582573
if title.level.name != Some(None) {
583574
buffer.append(buffer_msg_line_offset, title.level.as_str(), label_style);
584575
label_width += title.level.as_str().len();
585-
if let Some(Id { id: Some(id), url }) = id {
576+
if let Some(Id { id: Some(id), url }) = title.id {
586577
buffer.append(buffer_msg_line_offset, "[", label_style);
587578
if let Some(url) = url.as_ref() {
588579
buffer.append(

src/snippet.rs

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ pub(crate) const WARNING_TXT: &str = "warning";
1313
/// Top-level user message
1414
#[derive(Clone, Debug)]
1515
pub struct Message<'a> {
16-
pub(crate) id: Option<Id<'a>>, // for "correctness", could be sloppy and be on Title
1716
pub(crate) groups: Vec<Group<'a>>,
1817
}
1918

@@ -26,7 +25,15 @@ impl<'a> Message<'a> {
2625
///
2726
/// </div>
2827
pub fn id(mut self, id: &'a str) -> Self {
29-
self.id.get_or_insert(Id::default()).id = Some(id);
28+
let Some(Element::Title(title)) =
29+
self.groups.get_mut(0).and_then(|g| g.elements.first_mut())
30+
else {
31+
panic!(
32+
"Expected first element to be a Title, got: {:?}",
33+
self.groups
34+
);
35+
};
36+
title.id.get_or_insert(Id::default()).id = Some(id);
3037
self
3138
}
3239

@@ -36,7 +43,15 @@ impl<'a> Message<'a> {
3643
///
3744
/// </div>
3845
pub fn id_url(mut self, url: &'a str) -> Self {
39-
self.id.get_or_insert(Id::default()).url = Some(url);
46+
let Some(Element::Title(title)) =
47+
self.groups.get_mut(0).and_then(|g| g.elements.first_mut())
48+
else {
49+
panic!(
50+
"Expected first element to be a Title, got: {:?}",
51+
self.groups
52+
);
53+
};
54+
title.id.get_or_insert(Id::default()).url = Some(url);
4055
self
4156
}
4257

@@ -174,10 +189,41 @@ pub struct Padding;
174189
#[derive(Clone, Debug)]
175190
pub struct Title<'a> {
176191
pub(crate) level: Level<'a>,
192+
pub(crate) id: Option<Id<'a>>,
177193
pub(crate) title: &'a str,
178194
pub(crate) is_pre_styled: bool,
179195
}
180196

197+
impl<'a> Title<'a> {
198+
/// <div class="warning">
199+
///
200+
/// This is only relevant if the title is the first element of a group.
201+
///
202+
/// </div>
203+
/// <div class="warning">
204+
///
205+
/// Text passed to this function is considered "untrusted input", as such
206+
/// all text is passed through a normalization function. Pre-styled text is
207+
/// not allowed to be passed to this function.
208+
///
209+
/// </div>
210+
pub fn id(mut self, id: &'a str) -> Self {
211+
self.id.get_or_insert(Id::default()).id = Some(id);
212+
self
213+
}
214+
215+
/// <div class="warning">
216+
///
217+
/// This is only relevant if the title is the first element of a group and
218+
/// `id` present
219+
///
220+
/// </div>
221+
pub fn id_url(mut self, url: &'a str) -> Self {
222+
self.id.get_or_insert(Id::default()).url = Some(url);
223+
self
224+
}
225+
}
226+
181227
/// A source view [`Element`] in a [`Group`]
182228
///
183229
/// If you do not have [source][Snippet::source] available, see instead [`Origin`]

tests/formatter.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2642,8 +2642,9 @@ fn main() {
26422642
Group::new()
26432643
.element(
26442644
Level::HELP
2645-
.text(Some("suggestion[S0123]"))
2646-
.title("use `break` on its own without a value inside this `while` loop"),
2645+
.text(Some("suggestion"))
2646+
.title("use `break` on its own without a value inside this `while` loop")
2647+
.id("S0123"),
26472648
)
26482649
.element(
26492650
Snippet::source(source)

0 commit comments

Comments
 (0)