use crate::options::ParserOptions;
use crate::parser::blocks::headings::{emit_atx_heading, try_parse_atx_heading};
use crate::parser::utils::inline_emission;
use crate::syntax::SyntaxKind;
use rowan::GreenNodeBuilder;
#[derive(Debug, Clone)]
pub(crate) enum ListItemContent {
Text(String),
}
#[derive(Debug, Default, Clone)]
pub(crate) struct ListItemBuffer {
segments: Vec<ListItemContent>,
}
impl ListItemBuffer {
pub(crate) fn new() -> Self {
Self {
segments: Vec::new(),
}
}
pub(crate) fn push_text(&mut self, text: impl Into<String>) {
let text = text.into();
if text.is_empty() {
return;
}
self.segments.push(ListItemContent::Text(text));
}
pub(crate) fn is_empty(&self) -> bool {
self.segments.is_empty()
}
pub(crate) fn segment_count(&self) -> usize {
self.segments.len()
}
pub(crate) fn has_blank_lines_between_content(&self) -> bool {
log::trace!(
"has_blank_lines_between_content: segments={} result=false",
self.segments.len()
);
false
}
fn get_text_for_parsing(&self) -> String {
let mut result = String::new();
for segment in &self.segments {
let ListItemContent::Text(text) = segment;
result.push_str(text);
}
result
}
pub(crate) fn emit_as_block(
&self,
builder: &mut GreenNodeBuilder<'static>,
use_paragraph: bool,
config: &ParserOptions,
) {
if self.is_empty() {
return;
}
let text = self.get_text_for_parsing();
if !text.is_empty() {
let line_without_newline = text
.strip_suffix("\r\n")
.or_else(|| text.strip_suffix('\n'));
if let Some(line) = line_without_newline
&& !line.contains('\n')
&& !line.contains('\r')
&& let Some(level) = try_parse_atx_heading(line)
{
emit_atx_heading(builder, &text, level, config);
return;
}
}
let block_kind = if use_paragraph {
SyntaxKind::PARAGRAPH
} else {
SyntaxKind::PLAIN
};
builder.start_node(block_kind.into());
if !text.is_empty() {
inline_emission::emit_inlines(builder, &text, config);
}
builder.finish_node(); }
pub(crate) fn clear(&mut self) {
self.segments.clear();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_buffer_is_empty() {
let buffer = ListItemBuffer::new();
assert!(buffer.is_empty());
assert!(!buffer.has_blank_lines_between_content());
}
#[test]
fn test_push_single_text() {
let mut buffer = ListItemBuffer::new();
buffer.push_text("Hello, world!");
assert!(!buffer.is_empty());
assert!(!buffer.has_blank_lines_between_content());
assert_eq!(buffer.get_text_for_parsing(), "Hello, world!");
}
#[test]
fn test_push_multiple_text_segments() {
let mut buffer = ListItemBuffer::new();
buffer.push_text("Line 1\n");
buffer.push_text("Line 2\n");
buffer.push_text("Line 3");
assert_eq!(buffer.get_text_for_parsing(), "Line 1\nLine 2\nLine 3");
}
#[test]
fn test_clear_buffer() {
let mut buffer = ListItemBuffer::new();
buffer.push_text("Some text");
assert!(!buffer.is_empty());
buffer.clear();
assert!(buffer.is_empty());
assert_eq!(buffer.get_text_for_parsing(), "");
}
#[test]
fn test_empty_text_ignored() {
let mut buffer = ListItemBuffer::new();
buffer.push_text("");
assert!(buffer.is_empty());
}
}