script_meditate/
lib.rs

1//! This crate is intended to be used in (currently unstable) [Cargo
2//! scripts](https://doc.rust-lang.org/cargo/reference/unstable.html#script).
3//! It allows you to provide structured data and configuration inside a frontmatter comment, which
4//! can be parsed and obtained using a utility macro.
5//!
6//! # Data format support
7//!
8//! JSON, TOML, and YAML are currently supported.
9//! The desired format(s) must be enabled [through Cargo features](#frontmatter-format-selection).
10//! The type expected from parsing must implement [`Deserialize`](serde::Deserialize).
11//!
12//! The frontmatter comment is detected using the following pattern: `/*${tag}\n`, where `${tag}`
13//! is `json`, `toml`, or `yaml` (case-sensitive). The end of the frontmatter comment is detected
14//! using `\n*/\n` and must therefore not be found inside the data.
15//!
16//! # Note
17//!
18//! The script must not be placed directly inside the user's home directory.
19//!
20//! # Features
21#![cfg_attr(feature = "doc", doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#))]
22#![cfg_attr(docsrs, feature(doc_auto_cfg))]
23#![deny(clippy::pedantic)]
24#![deny(missing_docs)]
25
26#[cfg(feature = "json")]
27mod json;
28#[cfg(feature = "json")]
29#[doc(hidden)]
30pub use json::serde_json;
31
32#[cfg(feature = "toml")]
33mod toml;
34#[cfg(feature = "toml")]
35#[doc(hidden)]
36pub use toml::serde_toml;
37
38#[cfg(feature = "yaml")]
39mod yaml;
40#[cfg(feature = "yaml")]
41#[doc(hidden)]
42pub use yaml::serde_yaml;
43
44// Assumes that `\n*/\n` is not part of the JSON data.
45#[doc(hidden)]
46#[must_use]
47pub fn extract_frontmatter<'s>(source: &'s str, tag: &str) -> Option<&'s str> {
48    let start_pattern = format!("/*{tag}\n");
49    let end_pattern = "\n*/\n";
50    let from_comment_start = source.split_once(&start_pattern)?.1;
51    Some(from_comment_start.split_once(end_pattern)?.0)
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    #[test]
59    fn test_json_frontmatter_extraction() {
60        let source = r"
61/*json
62{
63}
64*/
65";
66
67        assert_eq!(extract_frontmatter(source, "json"), Some("{\n}"));
68    }
69
70    #[test]
71    fn test_no_frontmatter_found() {
72        let source = r"
73/*
74{
75}
76*/
77";
78
79        assert_eq!(extract_frontmatter(source, "json"), None);
80    }
81}