fn classy(chapter: &mut Chapter) -> Result<(), Error> {
    // 1. Parse the inbound markdown into an Event vector.
    let incoming_events: Vec<Event> = Parser::new(&chapter.content).collect();

    // 2. Find paragraphs beginning with the class annotator `{:.class-name}` and record their information in
    // a vector of ClassAnnotation structs.
    let mut class_annotations: Vec<Annotation> = vec![];
    for i in 0..incoming_events.len() {
        let event = &incoming_events[i];
        match *event {
            Event::Text(CowStr::Borrowed(text)) => {
                if i > 0 {
                    if let Event::Start(Tag::Paragraph) = incoming_events[i - 1] {
                        if let Ok((_, ald)) = attr_list_def(text) {
                            class_annotations.push(Annotation {
                                attr_list_def: ald,
                                paragraph_start: i - 1,
                                paragraph_end: None,
                            });
                        }
                    }
                }
            }
            Event::End(Tag::Paragraph) => {
                let last = class_annotations.last_mut();
                if let Some(class_command) = last {
                    if class_command.paragraph_end.is_none() {
                        class_command.paragraph_end = Some(i);
                    }
                }
            }
            _ => {}
        }
    }

    // 3. Construct a new_events vector with <div class="class-name">\n \n</div> around the annotated paragraphs
    // (and with the class annotation removed).
    let mut slices = vec![];
    let mut last_end = 0;
    let div_starts: Vec<Event> = class_annotations
        .iter()
        .map(|ca| Event::Html(CowStr::from(format!("{}", ca.attr_list_def))))
        .collect();
    let div_end: Vec<Event> = vec![Event::Html(CowStr::from("</div>"))];
    for (i, ca) in class_annotations.iter().enumerate() {
        // Add unclassed events.
        slices.push(&incoming_events[last_end..ca.paragraph_start]);

        last_end = ca.paragraph_end.unwrap_or(incoming_events.len() - 1);

        let paragraph = &incoming_events[ca.paragraph_start..=last_end];

        // Add <div class="class-name">
        slices.push(&div_starts[i..=i]);

        // Add paragraph opener.
        slices.push(&paragraph[0..1]);

        // Add the rest of the paragraph, skipping the class annotation.
        slices.push(&paragraph[2..]);

        // Add </div>.
        slices.push(&div_end[..]);
    }
    slices.push(&incoming_events[last_end..]);
    let new_events = slices.concat();

    // 4. Update chapter.content using markdown generated from the new event vector.
    let mut buf = String::with_capacity(chapter.content.len() + 128);
    pulldown_cmark_to_cmark::cmark(new_events.into_iter(), &mut buf, None)
        .expect("can re-render cmark");
    chapter.content = buf;
    Ok(())
}
/// This is where the markdown transformation actually happens.
/// Take paragraphs beginning with `{:.class-name}` and give them special rendering.
/// Mutation: the payload here is that it edits chapter.content.
This is where the markdown transformation actually happens.
Take paragraphs beginning with `{:.class-name}` and give them special rendering.
Mutation: the payload here is that it edits chapter.content.
This is where the markdown transformation actually happens . Take paragraphs beginning with ` { : . class - name } ` and give them special rendering . Mutation : the payload here is that it edits chapter . content .
fn classy(chapter: &mut Chapter) -> Result<(), Error> {
    // 1. Parse the inbound markdown into an Event vector.
    let incoming_events: Vec<Event> = Parser::new(&chapter.content).collect();
    // 2. Find paragraphs beginning with the class annotator `{:.class-name}` and record their information in
    // a vector of ClassAnnotation structs.
    let mut class_annotations: Vec<Annotation> = vec![];
    for i in 0..incoming_events.len() {
        let event = &incoming_events[i];
        match *event {
            Event::Text(CowStr::Borrowed(text)) => {
                if i > 0 {
                    if let Event::Start(Tag::Paragraph) = incoming_events[i - 1] {
                        if let Ok((_, ald)) = attr_list_def(text) {
                            class_annotations.push(Annotation {
                                attr_list_def: ald,
                                paragraph_start: i - 1,
                                paragraph_end: None,
                            });
                        }
                    }
                }
            }
            Event::End(Tag::Paragraph) => {
                let last = class_annotations.last_mut();
                if let Some(class_command) = last {
                    if class_command.paragraph_end.is_none() {
                        class_command.paragraph_end = Some(i);
                    }
                }
            }
            _ => {}
        }
    }
    // 3. Construct a new_events vector with <div class="class-name">\n \n</div> around the annotated paragraphs
    // (and with the class annotation removed).
    let mut slices = vec![];
    let mut last_end = 0;
    let div_starts: Vec<Event> = class_annotations
        .iter()
        .map(|ca| Event::Html(CowStr::from(format!("{}", ca.attr_list_def))))
        .collect();
    let div_end: Vec<Event> = vec![Event::Html(CowStr::from("</div>"))];
    for (i, ca) in class_annotations.iter().enumerate() {
        // Add unclassed events.
        slices.push(&incoming_events[last_end..ca.paragraph_start]);
        last_end = ca.paragraph_end.unwrap_or(incoming_events.len() - 1);
        let paragraph = &incoming_events[ca.paragraph_start..=last_end];
        // Add <div class="class-name">
        slices.push(&div_starts[i..=i]);
        // Add paragraph opener.
        slices.push(&paragraph[0..1]);
        // Add the rest of the paragraph, skipping the class annotation.
        slices.push(&paragraph[2..]);
        // Add </div>.
        slices.push(&div_end[..]);
    }
    slices.push(&incoming_events[last_end..]);
    let new_events = slices.concat();
    // 4. Update chapter.content using markdown generated from the new event vector.
    let mut buf = String::with_capacity(chapter.content.len() + 128);
    pulldown_cmark_to_cmark::cmark(new_events.into_iter(), &mut buf, None)
        .expect("can re-render cmark");
    chapter.content = buf;
    Ok(())
}
fn classy ( chapter : & mut Chapter ) -> Result < ( ) , Error > { // 1. Parse the inbound markdown into an Event vector. let incoming_events : Vec < Event > = Parser :: new ( & chapter . content ) . collect ( ) ; // 2. Find paragraphs beginning with the class annotator `{:.class-name}` and record their information in // a vector of ClassAnnotation structs. let mut class_annotations : Vec < Annotation > = vec ! [ ] ; for i in 0 .. incoming_events . len ( ) { let event = & incoming_events [ i ] ; match * event { Event :: Text ( CowStr :: Borrowed ( text ) ) => { if i > 0 { if let Event :: Start ( Tag :: Paragraph ) = incoming_events [ i - 1 ] { if let Ok ( ( _ , ald ) ) = attr_list_def ( text ) { class_annotations . push ( Annotation { attr_list_def : ald , paragraph_start : i - 1 , paragraph_end : None , } ) ; } } } } Event :: End ( Tag :: Paragraph ) => { let last = class_annotations . last_mut ( ) ; if let Some ( class_command ) = last { if class_command . paragraph_end . is_none ( ) { class_command . paragraph_end = Some ( i ) ; } } } _ => { } } } // 3. Construct a new_events vector with <div class="class-name">\n \n</div> around the annotated paragraphs // (and with the class annotation removed). let mut slices = vec ! [ ] ; let mut last_end = 0 ; let div_starts : Vec < Event > = class_annotations . iter ( ) . map ( | ca | Event :: Html ( CowStr :: from ( format ! ( " " ca attr_list_def ) ) ) ) . collect ( ) ; let div_end : Vec < Event > = vec ! [ Event Html ( CowStr from ( " " ) ) ] ; for ( i , ca ) in class_annotations . iter ( ) . enumerate ( ) { // Add unclassed events. slices . push ( & incoming_events [ last_end .. ca . paragraph_start ] ) ; last_end = ca . paragraph_end . unwrap_or ( incoming_events . len ( ) - 1 ) ; let paragraph = & incoming_events [ ca . paragraph_start ..= last_end ] ; // Add <div class="class-name"> slices . push ( & div_starts [ i ..= i ] ) ; // Add paragraph opener. slices . push ( & paragraph [ 0 .. 1 ] ) ; // Add the rest of the paragraph, skipping the class annotation. slices . push ( & paragraph [ 2 .. ] ) ; // Add </div>. slices . push ( & div_end [ .. ] ) ; } slices . push ( & incoming_events [ last_end .. ] ) ; let new_events = slices . concat ( ) ; // 4. Update chapter.content using markdown generated from the new event vector. let mut buf = String :: with_capacity ( chapter . content . len ( ) + 128 ) ; pulldown_cmark_to_cmark :: cmark ( new_events . into_iter ( ) , & mut buf , None ) . expect ( " " ) ; chapter . content = buf ; Ok ( ( ) ) }
This is where the markdown transformation actually happens.
This is where the markdown transformation actually happens .
chapter
&mut Chapter
chapter
&mut Chapter