From 87164cc2c996534759bb1f694ecee86ee6b28e87 Mon Sep 17 00:00:00 2001
From: ef3d0c3e
Date: Sun, 25 Aug 2024 14:16:08 +0200
Subject: [PATCH] Nested blockquotes
---
src/elements/blockquote.rs | 110 +++++++++++++++++++++----------------
1 file changed, 63 insertions(+), 47 deletions(-)
diff --git a/src/elements/blockquote.rs b/src/elements/blockquote.rs
index 48fd5c6..4afc8f7 100644
--- a/src/elements/blockquote.rs
+++ b/src/elements/blockquote.rs
@@ -22,8 +22,10 @@ use crate::compiler::compiler::Target;
use crate::compiler::compiler::Target::HTML;
use crate::document::document::Document;
use crate::document::element::ContainerElement;
+use crate::document::element::DocumentEnd;
use crate::document::element::ElemKind;
use crate::document::element::Element;
+use crate::elements::paragraph::Paragraph;
use crate::parser::parser::ParserState;
use crate::parser::rule::Rule;
use crate::parser::source::Cursor;
@@ -31,7 +33,6 @@ use crate::parser::source::Source;
use crate::parser::source::Token;
use crate::parser::source::VirtualSource;
use crate::parser::style::StyleHolder;
-use crate::parser::util::parse_paragraph;
use crate::parser::util::process_escaped;
use crate::parser::util::Property;
use crate::parser::util::PropertyParser;
@@ -127,13 +128,36 @@ impl Element for Blockquote {
result += format_author().map_err(|err| err.to_string())?.as_str();
}
- result += "";
+ let mut in_paragraph = false;
for elem in &self.content {
- result += elem
- .compile(compiler, document, cursor + result.len())?
- .as_str();
+ if elem.downcast_ref::().is_some() {}
+ else if elem.downcast_ref::().is_some()
+ {
+ if in_paragraph
+ {
+ result += "
";
+ in_paragraph = false;
+ }
+ result += elem
+ .compile(compiler, document, cursor + result.len())?
+ .as_str();
+ }
+ else
+ {
+ if !in_paragraph {
+ result += "";
+ in_paragraph = true;
+ }
+ result += elem
+ .compile(compiler, document, cursor + result.len())?
+ .as_str();
+ }
}
- result += "
";
+ if in_paragraph
+ {
+ result += "
";
+ }
+ result += "";
if self.style.author_pos == After {
result += format_author().map_err(|err| err.to_string())?.as_str();
}
@@ -274,7 +298,6 @@ impl Rule for BlockquoteRule {
// Content
let entry_start = captures.get(0).unwrap().start();
let mut entry_content = captures.get(2).unwrap().as_str().to_string();
- let mut spacing: Option<(Range, &str)> = None;
while let Some(captures) = self.continue_re.captures_at(content, end_cursor.pos) {
if captures.get(0).unwrap().start() != end_cursor.pos {
break;
@@ -282,38 +305,7 @@ impl Rule for BlockquoteRule {
// Advance cursor
end_cursor = end_cursor.at(captures.get(0).unwrap().end());
- // Spacing
- let current_spacing = captures.get(1).unwrap().as_str();
- if let Some(spacing) = &spacing {
- if spacing.1 != current_spacing {
- reports.push(
- Report::build(
- ReportKind::Warning,
- cursor.source.clone(),
- captures.get(1).unwrap().start(),
- )
- .with_message("Invalid Blockquote Spacing")
- .with_label(
- Label::new((
- cursor.source.clone(),
- captures.get(1).unwrap().range(),
- ))
- .with_message("Spacing for blockquote entries do not match")
- .with_color(state.parser.colors().warning),
- )
- .with_label(
- Label::new((cursor.source.clone(), spacing.0.clone()))
- .with_message("Previous spacing")
- .with_color(state.parser.colors().warning),
- )
- .finish(),
- );
- }
- } else {
- spacing = Some((captures.get(1).unwrap().range(), current_spacing));
- }
-
- entry_content += " ";
+ entry_content += "\n";
entry_content += captures.get(2).unwrap().as_str();
}
@@ -324,22 +316,38 @@ impl Rule for BlockquoteRule {
"Blockquote Entry".to_string(),
entry_content,
));
- let parsed_content = match parse_paragraph(state, entry_src, document) {
- Err(err) => {
+ // Parse content
+ let parsed_doc = state.with_state(|new_state| {
+ new_state.parser.parse(new_state, entry_src, Some(document)).0
+ });
+
+ // Extract paragraph and nested blockquotes
+ let mut parsed_content = vec![];
+ for mut elem in parsed_doc.content().borrow_mut().drain(..)
+ {
+ if let Some(paragraph) = elem.downcast_mut::()
+ {
+ parsed_content.extend(std::mem::take(&mut paragraph.content));
+ }
+ else if elem.downcast_ref::().is_some()
+ {
+ parsed_content.push(elem);
+ }
+ else
+ {
reports.push(
- Report::build(ReportKind::Warning, token.source(), token.range.start)
+ Report::build(ReportKind::Error, token.source(), token.range.start)
.with_message("Unable to Parse Blockquote Entry")
.with_label(
Label::new((token.source(), token.range.clone()))
- .with_message(err)
- .with_color(state.parser.colors().warning),
+ .with_message("Blockquotes may only contain paragraphs and other blockquotes")
+ .with_color(state.parser.colors().error),
)
.finish(),
);
return (end_cursor, reports);
}
- Ok(mut paragraph) => std::mem::take(&mut paragraph.content),
- };
+ }
// Get style
let style = state
@@ -431,6 +439,8 @@ BEFORE
> **
AFTER
> Another quote
+>>[author=B] Nested
+>>> More nested
END
"#
.to_string(),
@@ -448,12 +458,18 @@ END
} {
Text { content == "Some entry contin" };
Style;
- Text { content == "ued here " };
+ Text { content == "ued here" };
Style;
};
Paragraph { Text{ content == "AFTER" }; };
Blockquote {
Text { content == "Another quote" };
+ Blockquote { author == Some("B".to_string()) } {
+ Text { content == "Nested" };
+ Blockquote {
+ Text { content == "More nested" };
+ };
+ };
};
Paragraph { Text{ content == "END" }; };
);