use std::fmt::Write;
use shuck_config::{ConfigFieldMetadata, ConfigSectionMetadata, configuration_metadata};
pub fn generate_settings_reference() -> String {
let mut output = String::new();
output.push_str("# Settings Reference\n\n");
output.push_str("{/* This file is generated by `pnpm generate:config`. */}\n\n");
output.push_str(
"This page is generated from Shuck's Rust configuration metadata and lists the supported `shuck.toml` and `.shuck.toml` settings.\n\n",
);
output.push_str(
"Use [Configuration](/docs/configuration) for discovery, precedence, and examples of how config files are resolved.\n\n",
);
for section in configuration_metadata() {
emit_section(&mut output, section, &mut Vec::new());
}
output
}
fn emit_section(output: &mut String, section: &ConfigSectionMetadata, parents: &mut Vec<&str>) {
parents.push(section.key);
let path = parents.join(".");
let heading = if parents.len() == 1 { "##" } else { "###" };
let _ = writeln!(output, "{heading} `{}`\n", section_heading(&path));
output.push_str(section.docs);
output.push_str("\n\n");
for field in section.fields {
emit_field(output, field, &path);
}
for nested in section.sections {
emit_section(output, nested, parents);
}
parents.pop();
}
fn emit_field(output: &mut String, field: &ConfigFieldMetadata, section_path: &str) {
let _ = writeln!(output, "#### `{}`\n", field.key);
output.push_str(field.docs);
output.push_str("\n\n");
let _ = writeln!(output, "**Default value**: `{}`\n", field.default);
let _ = writeln!(output, "**Type**: `{}`\n", field.value_type);
output.push_str("**Example usage**:\n\n");
output.push_str("```toml\n");
emit_example_headers(output, section_path);
output.push_str(field.example);
output.push_str("\n```\n\n");
output.push_str("---\n\n");
}
fn section_heading(path: &str) -> String {
if path == "lint.contracts.custom" {
format!("[[{path}]]")
} else {
format!("[{path}]")
}
}
fn emit_example_headers(output: &mut String, section_path: &str) {
if section_path == "lint.contracts.custom" {
let _ = writeln!(output, "[[lint.contracts.custom]]");
} else if let Some(nested) = section_path.strip_prefix("lint.contracts.custom.") {
let _ = writeln!(output, "[[lint.contracts.custom]]");
let _ = writeln!(output, "[lint.contracts.custom.{nested}]");
} else {
let _ = writeln!(output, "[{section_path}]");
}
}
#[cfg(test)]
mod tests {
use super::generate_settings_reference;
#[test]
fn generated_reference_includes_known_sections() {
let reference = generate_settings_reference();
assert!(reference.contains("## `[check]`"));
assert!(reference.contains("## `[format]`"));
assert!(reference.contains("## `[lint]`"));
assert!(reference.contains("### `[lint.rule-options.c001]`"));
assert!(reference.contains("### `[[lint.contracts.custom]]`"));
assert!(reference.contains("[[lint.contracts.custom]]\nid ="));
assert!(
reference
.contains("[[lint.contracts.custom]]\n[lint.contracts.custom.consumes]\nnames =")
);
assert!(reference.contains("#### `embedded`"));
assert!(reference.contains("#### `indent-style`"));
}
}