use super::prelude::*;
use std::ops::{Deref, DerefMut};
pub const BLOCK_FOOTNOTE: BlockRule = BlockRule {
name: "block-footnote",
accepts_names: &["footnote"],
accepts_star: false,
accepts_score: false,
accepts_newlines: false,
parse_fn: parse_footnote_ref,
};
pub const BLOCK_FOOTNOTE_BLOCK: BlockRule = BlockRule {
name: "block-footnote-block",
accepts_names: &["footnoteblock"],
accepts_star: false,
accepts_score: false,
accepts_newlines: true,
parse_fn: parse_footnote_block,
};
fn parse_footnote_ref<'r, 't>(
parser: &mut Parser<'r, 't>,
name: &'t str,
flag_star: bool,
flag_score: bool,
in_head: bool,
) -> ParseResult<'r, 't, Elements<'t>> {
debug!("Parsing footnote ref block (in-head {in_head})");
if parser.in_footnote() {
return Err(parser.make_err(ParseErrorKind::FootnotesNested));
}
let parser = &mut ParserWrap::new(parser);
assert!(!flag_star, "Footnote reference doesn't allow star flag");
assert!(!flag_score, "Footnote reference doesn't allow score flag");
assert_block_name(&BLOCK_FOOTNOTE, name);
parser.get_head_none(&BLOCK_FOOTNOTE, in_head)?;
let (mut elements, errors, _) =
parser.get_body_elements(&BLOCK_FOOTNOTE, true)?.into();
if elements.len() == 1 {
match elements.pop().unwrap() {
Element::Container(container)
if container.ctype() == ContainerType::Paragraph =>
{
let mut new_elements: Vec<Element> = container.into();
elements.append(&mut new_elements);
}
element => elements.push(element),
};
}
parser.push_footnote(elements);
ok!(Element::Footnote, errors)
}
fn parse_footnote_block<'r, 't>(
parser: &mut Parser<'r, 't>,
name: &'t str,
flag_star: bool,
flag_score: bool,
in_head: bool,
) -> ParseResult<'r, 't, Elements<'t>> {
debug!("Parsing footnote list block (in-head {in_head})");
assert!(!flag_star, "Footnote block doesn't allow star flag");
assert!(!flag_score, "Footnote block doesn't allow score flag");
assert_block_name(&BLOCK_FOOTNOTE_BLOCK, name);
let mut arguments = parser.get_head_map(&BLOCK_FOOTNOTE_BLOCK, in_head)?;
let title = arguments.get("title");
let hide = arguments.get_bool(parser, "hide")?.unwrap_or(false);
if !arguments.is_empty() {
warn!("Invalid argument keys found");
return Err(parser.make_err(ParseErrorKind::BlockMalformedArguments));
}
parser.set_footnote_block();
ok!(Element::FootnoteBlock { title, hide })
}
#[derive(Debug)]
struct ParserWrap<'p, 'r, 't> {
parser: &'p mut Parser<'r, 't>,
}
impl<'p, 'r, 't> ParserWrap<'p, 'r, 't> {
#[inline]
fn new(parser: &'p mut Parser<'r, 't>) -> Self {
parser.set_footnote_flag(true);
ParserWrap { parser }
}
}
impl<'r, 't> Deref for ParserWrap<'_, 'r, 't> {
type Target = Parser<'r, 't>;
#[inline]
fn deref(&self) -> &Parser<'r, 't> {
self.parser
}
}
impl<'r, 't> DerefMut for ParserWrap<'_, 'r, 't> {
#[inline]
fn deref_mut(&mut self) -> &mut Parser<'r, 't> {
self.parser
}
}
impl Drop for ParserWrap<'_, '_, '_> {
fn drop(&mut self) {
self.parser.set_footnote_flag(false);
}
}