mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 21:43:37 +00:00
Correct complex list item support in AsciiDoc-to-Markdown conversion
Support for following cases are added: - newlines between list items - list item with multiline principal text with or without indent - list item immediately after a list continuation paragraph without empty lines in between
This commit is contained in:
parent
97ec0ea698
commit
86621a7cc0
1 changed files with 57 additions and 11 deletions
|
@ -42,7 +42,7 @@ impl<'a, 'b, R: BufRead> Converter<'a, 'b, R> {
|
||||||
} else if line.starts_with(VIDEO_BLOCK_PREFIX) {
|
} else if line.starts_with(VIDEO_BLOCK_PREFIX) {
|
||||||
self.process_video_block(None, 0)?;
|
self.process_video_block(None, 0)?;
|
||||||
} else {
|
} else {
|
||||||
self.process_paragraph(0)?;
|
self.process_paragraph(0, |line| line.is_empty())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.skip_blank_lines()?;
|
self.skip_blank_lines()?;
|
||||||
|
@ -84,16 +84,19 @@ impl<'a, 'b, R: BufRead> Converter<'a, 'b, R> {
|
||||||
|
|
||||||
fn process_list(&mut self) -> anyhow::Result<()> {
|
fn process_list(&mut self) -> anyhow::Result<()> {
|
||||||
let mut nesting = ListNesting::new();
|
let mut nesting = ListNesting::new();
|
||||||
while let Some(line) = self.iter.next() {
|
while let Some(line) = self.iter.peek() {
|
||||||
let line = line?;
|
let line = line.as_deref().map_err(|e| anyhow!("{e}"))?;
|
||||||
if line.is_empty() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some((marker, item)) = get_list_item(&line) {
|
if get_list_item(&line).is_some() {
|
||||||
|
let line = self.iter.next().unwrap()?;
|
||||||
|
let (marker, item) = get_list_item(&line).unwrap();
|
||||||
nesting.set_current(marker);
|
nesting.set_current(marker);
|
||||||
self.write_list_item(item, &nesting);
|
self.write_list_item(item, &nesting);
|
||||||
|
self.process_paragraph(nesting.indent(), |line| {
|
||||||
|
line.is_empty() || get_list_item(line).is_some() || line == "+"
|
||||||
|
})?;
|
||||||
} else if line == "+" {
|
} else if line == "+" {
|
||||||
|
let _ = self.iter.next().unwrap()?;
|
||||||
let line = self
|
let line = self
|
||||||
.iter
|
.iter
|
||||||
.peek()
|
.peek()
|
||||||
|
@ -118,11 +121,17 @@ impl<'a, 'b, R: BufRead> Converter<'a, 'b, R> {
|
||||||
self.process_video_block(None, indent)?;
|
self.process_video_block(None, indent)?;
|
||||||
} else {
|
} else {
|
||||||
self.write_line("", 0);
|
self.write_line("", 0);
|
||||||
self.process_paragraph(indent)?;
|
let current = nesting.current().unwrap();
|
||||||
|
self.process_paragraph(indent, |line| {
|
||||||
|
line.is_empty()
|
||||||
|
|| get_list_item(line).filter(|(m, _)| m == current).is_some()
|
||||||
|
|| line == "+"
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bail!("not a list block")
|
break;
|
||||||
}
|
}
|
||||||
|
self.skip_blank_lines()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -235,15 +244,19 @@ impl<'a, 'b, R: BufRead> Converter<'a, 'b, R> {
|
||||||
bail!("not a video block")
|
bail!("not a video block")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_paragraph(&mut self, level: usize) -> anyhow::Result<()> {
|
fn process_paragraph<P>(&mut self, level: usize, predicate: P) -> anyhow::Result<()>
|
||||||
|
where
|
||||||
|
P: Fn(&str) -> bool,
|
||||||
|
{
|
||||||
while let Some(line) = self.iter.peek() {
|
while let Some(line) = self.iter.peek() {
|
||||||
let line = line.as_deref().map_err(|e| anyhow!("{e}"))?;
|
let line = line.as_deref().map_err(|e| anyhow!("{e}"))?;
|
||||||
if line.is_empty() || (level > 0 && line == "+") {
|
if predicate(&line) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.write_indent(level);
|
self.write_indent(level);
|
||||||
let line = self.iter.next().unwrap()?;
|
let line = self.iter.next().unwrap()?;
|
||||||
|
let line = line.trim_start();
|
||||||
if line.ends_with('+') {
|
if line.ends_with('+') {
|
||||||
let line = &line[..(line.len() - 1)];
|
let line = &line[..(line.len() - 1)];
|
||||||
self.output.push_str(line);
|
self.output.push_str(line);
|
||||||
|
@ -373,6 +386,10 @@ impl ListNesting {
|
||||||
Self(Vec::<ListMarker>::with_capacity(6))
|
Self(Vec::<ListMarker>::with_capacity(6))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn current(&mut self) -> Option<&ListMarker> {
|
||||||
|
self.0.last()
|
||||||
|
}
|
||||||
|
|
||||||
fn set_current(&mut self, marker: ListMarker) {
|
fn set_current(&mut self, marker: ListMarker) {
|
||||||
let Self(markers) = self;
|
let Self(markers) = self;
|
||||||
if let Some(index) = markers.iter().position(|m| *m == marker) {
|
if let Some(index) = markers.iter().position(|m| *m == marker) {
|
||||||
|
@ -469,6 +486,22 @@ rustup update nightly
|
||||||
----
|
----
|
||||||
This is a plain listing.
|
This is a plain listing.
|
||||||
----
|
----
|
||||||
|
* single line item followed by empty lines
|
||||||
|
|
||||||
|
* multiline list
|
||||||
|
item followed by empty lines
|
||||||
|
|
||||||
|
* multiline list
|
||||||
|
item with indent
|
||||||
|
|
||||||
|
* multiline list
|
||||||
|
item not followed by empty lines
|
||||||
|
* multiline list
|
||||||
|
item followed by different marker
|
||||||
|
** foo
|
||||||
|
** bar
|
||||||
|
* multiline list
|
||||||
|
item followed by list continuation
|
||||||
+
|
+
|
||||||
paragraph
|
paragraph
|
||||||
paragraph
|
paragraph
|
||||||
|
@ -539,6 +572,19 @@ Release: release:2022-01-01[]
|
||||||
```
|
```
|
||||||
This is a plain listing.
|
This is a plain listing.
|
||||||
```
|
```
|
||||||
|
- single line item followed by empty lines
|
||||||
|
- multiline list
|
||||||
|
item followed by empty lines
|
||||||
|
- multiline list
|
||||||
|
item with indent
|
||||||
|
- multiline list
|
||||||
|
item not followed by empty lines
|
||||||
|
- multiline list
|
||||||
|
item followed by different marker
|
||||||
|
- foo
|
||||||
|
- bar
|
||||||
|
- multiline list
|
||||||
|
item followed by list continuation
|
||||||
|
|
||||||
paragraph
|
paragraph
|
||||||
paragraph
|
paragraph
|
||||||
|
|
Loading…
Reference in a new issue