markdown-formatter 0.0.13

Flavored Markdown (ZH) content formatter
Documentation
pub fn split_into_lines(input: String, limit: usize) -> Vec<String> {
    let mut output: Vec<String> = vec![];
    let mut cur_line: Vec<char> = vec![];
    let mut cur_line_len: usize = 0;
    input.trim()
        .replace("\n", " &#LF#&!")
        .split(" ")
        .for_each(|space_separated| {
            let mut space_separated: String = space_separated.to_string();
            if cur_line_len == limit || cur_line_len + 1 == limit {
                // 长度足够一行,提交
                output.push(cur_line.clone().into_iter().collect());
                cur_line.clear();
                cur_line_len = 0;
            }
            if space_separated.starts_with("&#LF#&!") {
                if cur_line_len > 0 {
                    output.push(cur_line.clone().into_iter().collect());
                    cur_line.clear();
                    cur_line_len = 0;
                }else {
                    output.push("".to_string());
                }
                space_separated = space_separated.replace("&#LF#&!", "");
            }
            let len_of_space_separated = len_of_chars(&space_separated);
            if len_of_space_separated == 0 {
                return;
            }
            if len_of_space_separated + cur_line_len < limit {
                // 加入也不会超长,直接放入
                if cur_line_len > 0 {
                    // 当前已经记录的字符不为空时才需要空格
                    cur_line.push(' ');
                    cur_line_len += 1;
                }
                cur_line.extend(space_separated.chars());
                cur_line_len += len_of_space_separated;
            } else {
                // 加入超长,需要判断
                if cur_line_len < limit && cur_line_len > 0 {
                    // 全部放入长度也没有超,先提交现有的
                    output.push(cur_line.clone().into_iter().collect());
                    cur_line.clear();
                    cur_line_len = 0;
                }

                space_separated.chars().for_each(|ch| {
                    match ch {
                        '\u{4E00}'..='\u{9FCC}'
                        | '\u{3400}'..='\u{4DB5}'
                        | '\u{20000}'..='\u{2A6D6}'
                        | '\u{2A700}'..='\u{2B734}'
                        | '\u{2B740}'..='\u{2B81D}' => {
                            // CJK,每个字符占两个位置
                            cur_line_len += 2;
                        }
                        _ => {
                            cur_line_len += 1;
                        }
                    }
                    // 一个一个字符放入
                    cur_line.push(ch);
                    if cur_line_len == limit || cur_line_len == limit - 1 {
                        // 长度足够一行,提交
                        output.push(cur_line.clone().into_iter().collect());
                        cur_line.clear();
                        cur_line_len = 0;
                    }
                });
            }
        });

    if cur_line_len > 0 {
        output.push(cur_line.into_iter().collect());
    }

    output
}

pub fn len_of_chars(input: &str) -> usize {
    let mut size = 0;
    input.chars().for_each(|ch| {
        match ch {
            '\u{4E00}'..='\u{9FCC}'
            | '\u{3400}'..='\u{4DB5}'
            | '\u{20000}'..='\u{2A6D6}'
            | '\u{2A700}'..='\u{2B734}'
            | '\u{2B740}'..='\u{2B81D}' => {
                // CJK,每个字符占两个位置
                size += 2;
            }
            _ => {
                size += 1;
            }
        }
    });
    size
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_split_into_lines() {
        let input = String::from("This is a long line. ".repeat(10));
        assert_eq!(split_into_lines(input, 80).len(), 3);

        let input = String::from("这是一段很长的介绍\n".repeat(10));
        println!("{:?}", split_into_lines(input, 71));
        // assert_eq!(split_into_lines(input, 80).len(), 3);
    }
}