1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
//! A library that allows a user to extract and arbitrary number of lines of "frontmatter" from the start of any multiline string.
//!
//! Included is some basic auto-detection of what lines are considered to be part of the frontmatter, but erroneous detection can be prevented by tuning the copnfiguration.
//!
//! Note that absolutely no parsing of extracted frontmatter is performed; this is designed to output its results for another library to then parse.
//!
//! # Example
//!
//! Given a variable `input` with the following text:
//!
//! ```md
//! <!--
//! parent:
//!   - item1
//!   - item2
//! -->
//!
//! # Title
//!
//! This is an example markdown document.
//! ```
//!
//! ... and the following code:
//!
//! ```rust
//! # const input: &str = include_str!("../resources/tests/discard_first_and_number_or_end_line_example.md");
//! use extract_frontmatter::{Config, extract};
//! let config = Config::new(None, Some("-->"), None, true);
//! let output = extract(&config, input);
//! # assert_eq!(output, include_str!("../resources/tests/output.yml").trim());
//! ```
//!
//! ... the variable `output` will contain:
//!
//! ```yml
//! parent:
//!   - item1
//!   - item2
//! ```

// Enable all clippy lints and enforce, and opt out of individual lints
#![cfg_attr(feature = "cargo-clippy", warn(clippy::cargo, clippy::pedantic, clippy::nursery))]
#![cfg_attr(feature = "cargo-clippy", allow(clippy::must_use_candidate))]

pub use crate::config::Config;

mod config;
mod frontmatter;

/// Extract frontmatter from the given string using the provided configuration.
///
/// # Arguments
///
/// | Argument | Description |
/// | --- | --- |
/// | `config` | The configuration to use when extracting frontmatter |
/// | `input` | The text to extract frontmatter from |
pub fn extract(config: &Config, input: &str) -> String {
    let lines = frontmatter::get_lines(config, input);
    frontmatter::clean(config, lines).join("\n")
}

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

    const INPUT_DISCARD_FIRST_AND_NUMBER_OR_END_LINE: &str =
        include_str!("../resources/tests/discard_first_and_number_or_end_line_example.md");
    const INPUT_LEAD_CHARS: &str = include_str!("../resources/tests/lead_chars_example.scad");
    const INPUT_END_LINE_AND_LEAD_CHARS: &str = include_str!("../resources/tests/end_line_and_lead_chars_example.scad");

    const OUTPUT: &str = include_str!("../resources/tests/output.yml");

    #[test]
    fn test_extract_by_discard_first_and_number() {
        let config = Config::new(Some(4), None, None, true);
        let output = extract(&config, INPUT_DISCARD_FIRST_AND_NUMBER_OR_END_LINE);
        assert_eq!(output, OUTPUT.trim())
    }

    #[test]
    fn test_extract_by_discard_first_and_end_line() {
        let config = Config::new(None, Some("-->"), None, true);
        let output = extract(&config, INPUT_DISCARD_FIRST_AND_NUMBER_OR_END_LINE);
        assert_eq!(output, OUTPUT.trim())
    }

    #[test]
    fn test_extract_by_lead_chars() {
        let config = Config::new(None, None, Some("// "), false);
        let output = extract(&config, INPUT_LEAD_CHARS);
        assert_eq!(output, OUTPUT.trim())
    }

    #[test]
    fn test_extract_by_end_line_and_lead_chars() {
        let config = Config::new(None, Some("END"), Some("// "), false);
        let output = extract(&config, INPUT_END_LINE_AND_LEAD_CHARS);
        assert_eq!(output, OUTPUT.trim())
    }
}