prepass: fix referenced headings with e.g. spaces
headings that did not exactly match their ids were previously not matched with their reference
This commit is contained in:
parent
45c86da274
commit
9efd4e4448
1 changed files with 59 additions and 2 deletions
61
src/lib.rs
61
src/lib.rs
|
@ -579,6 +579,8 @@ struct Heading {
|
|||
location: usize,
|
||||
/// Automatically generated id from heading text.
|
||||
id_auto: String,
|
||||
/// Text of heading, formatting stripped.
|
||||
text: String,
|
||||
/// Overriding id from an explicit attribute on the heading.
|
||||
id_override: Option<String>,
|
||||
}
|
||||
|
@ -630,6 +632,7 @@ impl<'s> PrePass<'s> {
|
|||
.map(ToString::to_string);
|
||||
|
||||
let mut id_auto = String::new();
|
||||
let mut text = String::new();
|
||||
let mut last_whitespace = true;
|
||||
let inlines = tree.take_inlines().collect::<Vec<_>>();
|
||||
inline_parser.reset();
|
||||
|
@ -637,6 +640,7 @@ impl<'s> PrePass<'s> {
|
|||
inline_parser.feed_line(*sp, i == inlines.len() - 1);
|
||||
inline_parser.for_each(|ev| match ev.kind {
|
||||
inline::EventKind::Str => {
|
||||
text.push_str(ev.span.of(src));
|
||||
let mut chars = ev.span.of(src).chars().peekable();
|
||||
while let Some(c) = chars.next() {
|
||||
if c.is_whitespace() {
|
||||
|
@ -654,6 +658,7 @@ impl<'s> PrePass<'s> {
|
|||
}
|
||||
}
|
||||
inline::EventKind::Atom(inline::Atom::Softbreak) => {
|
||||
text.push(' ');
|
||||
id_auto.push('-');
|
||||
}
|
||||
_ => {}
|
||||
|
@ -686,6 +691,7 @@ impl<'s> PrePass<'s> {
|
|||
headings.push(Heading {
|
||||
location: e.span.start(),
|
||||
id_auto,
|
||||
text,
|
||||
id_override,
|
||||
});
|
||||
}
|
||||
|
@ -703,7 +709,7 @@ impl<'s> PrePass<'s> {
|
|||
}
|
||||
|
||||
let mut headings_lex = (0..headings.len()).collect::<Vec<_>>();
|
||||
headings_lex.sort_by_key(|i| &headings[*i].id_auto);
|
||||
headings_lex.sort_by_key(|i| &headings[*i].text);
|
||||
|
||||
Self {
|
||||
link_definitions,
|
||||
|
@ -726,7 +732,7 @@ impl<'s> PrePass<'s> {
|
|||
|
||||
fn heading_id_by_tag(&self, tag: &str) -> Option<&str> {
|
||||
self.headings_lex
|
||||
.binary_search_by_key(&tag, |i| &self.headings[*i].id_auto)
|
||||
.binary_search_by_key(&tag, |i| &self.headings[*i].text)
|
||||
.ok()
|
||||
.map(|i| self.heading_id(i))
|
||||
}
|
||||
|
@ -1149,6 +1155,57 @@ mod test {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn heading_ref() {
|
||||
test_parse!(
|
||||
concat!(
|
||||
"A [link][Some Section] to another section.\n", //
|
||||
"\n", //
|
||||
"# Some Section", //
|
||||
),
|
||||
Start(Paragraph, Attributes::new()),
|
||||
Str("A ".into()),
|
||||
Start(
|
||||
Link(
|
||||
"#Some-Section".into(),
|
||||
LinkType::Span(SpanLinkType::Reference)
|
||||
),
|
||||
Attributes::new()
|
||||
),
|
||||
Str("link".into()),
|
||||
End(Link(
|
||||
"#Some-Section".into(),
|
||||
LinkType::Span(SpanLinkType::Reference)
|
||||
)),
|
||||
Str(" to another section.".into()),
|
||||
End(Paragraph),
|
||||
Blankline,
|
||||
Start(
|
||||
Section {
|
||||
id: "Some-Section".into()
|
||||
},
|
||||
Attributes::new()
|
||||
),
|
||||
Start(
|
||||
Heading {
|
||||
level: 1,
|
||||
has_section: true,
|
||||
id: "Some-Section".into(),
|
||||
},
|
||||
Attributes::new(),
|
||||
),
|
||||
Str("Some Section".into()),
|
||||
End(Heading {
|
||||
level: 1,
|
||||
has_section: true,
|
||||
id: "Some-Section".into(),
|
||||
}),
|
||||
End(Section {
|
||||
id: "Some-Section".into()
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn blockquote() {
|
||||
test_parse!(
|
||||
|
|
Loading…
Reference in a new issue