fml 0.6.8

Friendly Markup Language
Documentation
use super::{
    Stream,
    macros::{not, slice_till},
};
use crate::{
    ast::FmlValue,
    parser::{State, functions::styles::code_block},
};
use winnow::{
    Result,
    ascii::*,
    combinator::*,
    error::{ContextError, ParserError, StrContext},
    prelude::*,
    token::*,
};

fn section_sep<'i>(input: &mut Stream<'i>) -> Result<&'i str> {
    repeat(2.., (space0, line_ending, space0).take())
        .map(|()| ())
        .take()
        .parse_next(input)
}

fn section_body<'i>(input: &mut Stream<'i>) -> Result<&'i str> {
    let sep = || alt((section_sep, eof));
    let codeblock = || preceded(not(r"\```"), code_block.take());
    let other_end = || alt((r"\```", codeblock(), sep()));
    let other = slice_till!(1.., not!(other_end()));
    let inner = alt((r"\```", codeblock(), other));

    slice_till!(1.., inner, peek(sep())).parse_next(input)
}

fn sections<'i>(input: &mut Stream<'i>) -> Result<Vec<&'i str>> {
    delimited(
        multispace0,
        separated(0.., section_body, section_sep),
        multispace0,
    )
    .parse_next(input)
}

pub fn split_sections<'i>(input: &'i str) -> Result<Vec<&'i str>> {
    // Stateful stream is only used here for clean compatibility with the code_block style in use.
    let input = Stream {
        input,
        state: State::default(),
    };
    // We use `parse` instead of `parse_next` to ensure that the entire
    // input has been parsed and split into sections.
    let res = sections.parse(input);
    res.map_err(|e| e.into_inner())
}