dprint-plugin-markdown 0.21.1

Markdown formatter for dprint.
Documentation
use crate::generation::common::*;

pub fn parse_text_in_brackets(start_pos: usize, char_scanner: &mut CharScanner) -> Result<String, ParseError> {
  parse_text_in_container(start_pos, char_scanner, '[', ']')
}

pub fn parse_text_in_parens(start_pos: usize, char_scanner: &mut CharScanner) -> Result<String, ParseError> {
  parse_text_in_container(start_pos, char_scanner, '(', ')')
}

fn parse_text_in_container(
  start_pos: usize,
  char_scanner: &mut CharScanner,
  open_char: char,
  close_char: char,
) -> Result<String, ParseError> {
  let mut text = String::new();
  while let Some((byte_pos, c)) = char_scanner.next() {
    if c == close_char {
      return Ok(text);
    } else if c == open_char {
      return Err(ParseError::new(
        Range {
          start: byte_pos,
          end: byte_pos + c.len_utf8(),
        },
        format!("Unexpected open container char `{}`.", open_char),
      ));
    } else {
      text.push(c);
    }
  }

  Err(ParseError::new(
    Range {
      start: start_pos,
      end: char_scanner.pos(),
    },
    format!("Did not find container close char `{}`.", close_char),
  ))
}

pub fn parse_link_url_and_title(text: &str) -> (String, Option<String>) {
  let mut char_scanner = CharScanner::new(0, text);
  let mut url = String::new();
  let mut title: Option<String> = None;

  char_scanner.skip_spaces();

  while let Some((_, c)) = char_scanner.next() {
    match c {
      '"' => match try_parse_title(&mut char_scanner) {
        Ok(text) => title = Some(text),
        Err(text) => {
          url.push('"');
          url.push_str(&text);
        }
      },
      _ => url.push(c),
    }
  }

  (url, title)
}

fn try_parse_title(char_scanner: &mut CharScanner) -> Result<String, String> {
  let mut text = String::new();

  while let Some((_, c)) = char_scanner.next() {
    match c {
      '"' => {
        if char_scanner.peek().is_some() {
          text.push('"');
          return Err(text);
        }
        return Ok(text);
      }
      _ => text.push(c),
    }
  }

  Err(text)
}