zenith-tool 0.0.7

The Zenith command-line interface (the `zenith` binary) for the design-document toolchain.
Documentation
//! Embedded skill assets and small accessors over them.
//!
//! The `SKILL_FILES` / `COMMAND_FILES` tables are generated by `build.rs` from
//! the canonical skill source under `assets/skill` and `assets/plugin-commands`.

include!(concat!(env!("OUT_DIR"), "/skill_assets.rs"));

/// The relative path of the skill's entry file within `SKILL_FILES`.
pub const SKILL_ENTRY: &str = "SKILL.md";

/// Look up an embedded skill file by its relative path.
pub fn skill_file(rel: &str) -> Option<&'static str> {
    SKILL_FILES
        .iter()
        .find(|(name, _)| *name == rel)
        .map(|(_, body)| *body)
}

/// The raw `SKILL.md` (with its YAML frontmatter), as authored.
pub fn skill_md_raw() -> &'static str {
    skill_file(SKILL_ENTRY).unwrap_or("")
}

/// The `SKILL.md` body with any leading YAML frontmatter removed.
pub fn skill_md_body() -> &'static str {
    strip_frontmatter(skill_md_raw())
}

/// The `description:` field from the skill frontmatter, if present.
pub fn skill_description() -> Option<String> {
    frontmatter(skill_md_raw()).and_then(|fm| {
        fm.lines()
            .find_map(|l| l.trim().strip_prefix("description:"))
            .map(|v| unquote(v.trim()))
    })
}

/// Split a `---` frontmatter block off the front of `s`, accepting LF or CRLF.
/// Returns `(frontmatter_without_fences, body)`.
fn split_frontmatter(s: &str) -> (Option<&str>, &str) {
    let s = s.strip_prefix('\u{feff}').unwrap_or(s);
    let rest = if let Some(rest) = s.strip_prefix("---\r\n") {
        rest
    } else if let Some(rest) = s.strip_prefix("---\n") {
        rest
    } else {
        return (None, s);
    };

    for (line_start, line) in rest.split_inclusive('\n').scan(0usize, |offset, line| {
        let line_start = *offset;
        *offset += line.len();
        Some((line_start, line))
    }) {
        if line.trim_end_matches(['\r', '\n']) == "---" {
            return (Some(&rest[..line_start]), &rest[line_start + line.len()..]);
        }
    }

    (None, s)
}

fn frontmatter(s: &str) -> Option<&str> {
    split_frontmatter(s).0
}

fn strip_frontmatter(s: &str) -> &str {
    split_frontmatter(s).1
}

/// Strip a single pair of surrounding double or single quotes.
fn unquote(s: &str) -> String {
    let bytes = s.as_bytes();
    if bytes.len() >= 2 {
        let first = bytes[0];
        let last = bytes[bytes.len() - 1];
        if (first == b'"' && last == b'"') || (first == b'\'' && last == b'\'') {
            return s[1..s.len() - 1].to_owned();
        }
    }
    s.to_owned()
}

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

    #[test]
    fn split_frontmatter_accepts_lf() {
        let (fm, body) = split_frontmatter("---\ndescription: test\n---\n# Body\n");

        assert_eq!(fm, Some("description: test\n"));
        assert_eq!(body, "# Body\n");
    }

    #[test]
    fn split_frontmatter_accepts_crlf() {
        let (fm, body) = split_frontmatter("---\r\ndescription: test\r\n---\r\n# Body\r\n");

        assert_eq!(fm, Some("description: test\r\n"));
        assert_eq!(body, "# Body\r\n");
    }

    #[test]
    fn split_frontmatter_accepts_utf8_bom() {
        let (fm, body) = split_frontmatter("\u{feff}---\r\ndescription: test\r\n---\r\n# Body\r\n");

        assert_eq!(fm, Some("description: test\r\n"));
        assert_eq!(body, "# Body\r\n");
    }

    #[test]
    fn split_frontmatter_leaves_plain_markdown_unchanged() {
        let input = "# Body\n---\nnot frontmatter\n";

        assert_eq!(split_frontmatter(input), (None, input));
    }
}