cartulary 0.3.0-alpha.1

The knowledge layer of your project — decisions, issues, docs, all in one place.
Documentation
//! Shared helpers for building YAML frontmatter in `save()` implementations.

use crate::domain::model::entity_ref::EntityRef;

/// Append a `links:` YAML block to `out`.
///
/// Each link is written as `- id: <target>\n    relationship: <rel>\n`.
/// Does nothing if `links` is empty.
pub fn write_links<'a>(
    out: &mut String,
    links: impl Iterator<Item = (&'a EntityRef, &'a str)>,
    has_links: bool,
) {
    if !has_links {
        return;
    }
    out.push_str("links:\n");
    for (target, relationship) in links {
        out.push_str(&format!("  - id: {target}\n"));
        out.push_str(&format!("    relationship: {relationship}\n"));
    }
}

/// Append a `relates:` YAML block to `out`.
///
/// Each target is written as `- <id>\n`. Does nothing if `relates` is
/// empty. Cross-kind "see also" pointers are flat (no relationship verb,
/// no nested mapping), reflecting their ad-hoc semantics versus typed
/// `links:`. See DDR-018QWJVHRH35B and ISSUE-018P03NSC7VNQ.
pub fn write_relates<'a>(out: &mut String, relates: impl Iterator<Item = &'a EntityRef>) {
    let mut peekable = relates.peekable();
    if peekable.peek().is_none() {
        return;
    }
    out.push_str("relates:\n");
    for target in peekable {
        out.push_str(&format!("  - {target}\n"));
    }
}

/// Append a `tags:` YAML block to `out`.
///
/// Each tag is written as `- <tag>\n`. Tags that contain a `:` (the
/// structured `<key>:<value>` form, ISSUE-0110) are wrapped in double quotes
/// so the YAML round-trip is unambiguous — naked `area:backend` could be
/// misread as a mapping by some parsers. Plain tags stay unquoted for
/// readability. Does nothing if `tags` is empty.
pub fn write_tags<'a>(out: &mut String, tags: impl Iterator<Item = &'a str>, has_tags: bool) {
    if !has_tags {
        return;
    }
    out.push_str("tags:\n");
    for tag in tags {
        if tag.contains(':') {
            out.push_str(&format!("  - \"{tag}\"\n"));
        } else {
            out.push_str(&format!("  - {tag}\n"));
        }
    }
}

/// Append an `aliases:` YAML block to `out`.
///
/// Each alias is written as `- "<value>"\n` (quoted to keep YAML
/// unambiguous when the alias contains `:` or other reserved chars). Does
/// nothing if `aliases` is empty. ADR-0022.
pub fn write_aliases<'a>(out: &mut String, aliases: impl Iterator<Item = &'a str>) {
    let mut peekable = aliases.peekable();
    if peekable.peek().is_none() {
        return;
    }
    out.push_str("aliases:\n");
    for alias in peekable {
        out.push_str(&format!("  - \"{alias}\"\n"));
    }
}