Skip to content

Commit 11a7416

Browse files
bordeuxclaude
andcommitted
feat: add --validate option for output format validation
Add validation feature to ensure rendered template output conforms to expected formats (JSON, YAML, or TOML) before writing to file or stdout. ## Features - Add `--validate <FORMAT>` CLI option (json, yaml, or toml) - Validates output format after rendering, before output - Returns error code 1 on validation failure - Silent on success (errors only), no unnecessary output messages ## Implementation ### New Modules - Create src/validator.rs with validation logic - `validate_json()` - Parse and validate JSON syntax - `validate_yaml()` - Parse and validate YAML syntax - `validate_toml()` - Parse and validate TOML syntax - Detailed error messages with common mistake hints ### CLI Changes - Add `ValidateFormat` enum (Json, Yaml, Toml) to cli.rs - Add `--validate` argument using clap's ValueEnum ### Core Integration - Update `render_template()` signature to accept `Option<ValidateFormat>` - Validate output after rendering, before writing to file/stdout - Update all test files to pass `None` for validate parameter ### Testing - Add tests/test_validation.rs with 10 integration tests - Valid/invalid cases for each format - Output preservation tests - File output with validation - Default behavior without --validate flag - Add 20+ unit tests in validator.rs module - Add tempfile dev dependency for integration tests ## Documentation - Update README.md with --validate option documentation - Add usage examples for each format - Document validation behavior (silent success, error on failure) ## Use Cases ```bash # Validate JSON configuration tmpltool config.json.tmpl --validate json # Validate Kubernetes YAML manifests tmpltool deployment.yaml.tmpl --validate yaml -o deploy.yaml # Validate TOML build configuration tmpltool Cargo.toml.tmpl --validate toml ``` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent b8d19c9 commit 11a7416

26 files changed

Lines changed: 603 additions & 8 deletions

Cargo.lock

Lines changed: 49 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,6 @@ base64 = "0.22"
3434
hex = "0.4"
3535
bcrypt = "0.16"
3636
hmac = "0.12"
37+
38+
[dev-dependencies]
39+
tempfile = "3.24.0"

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,10 @@ cat template.txt | tmpltool [OPTIONS]
150150
- `-o, --output <FILE>` - Output file path (prints to stdout if not specified)
151151
- `--trust` - Trust mode: Allow filesystem functions to access absolute paths and parent directories
152152
- **WARNING:** Only use with trusted templates. Disables security restrictions.
153+
- `--validate <FORMAT>` - Validate output format (json, yaml, or toml)
154+
- Validates the rendered output conforms to the specified format
155+
- Exits with error code 1 if validation fails
156+
- No output on success, error message only on validation failure
153157

154158
### Input/Output Patterns
155159

@@ -181,6 +185,16 @@ cat k8s-deployment.yaml.tmpl | tmpltool | kubectl apply -f -
181185

182186
# Trust mode for system files
183187
tmpltool --trust system_info.tmpl # Can read /etc/passwd, etc.
188+
189+
# Validate JSON output
190+
tmpltool config.json.tmpl --validate json
191+
# Exits with error if output is invalid JSON
192+
193+
# Validate YAML output
194+
tmpltool k8s-deploy.yaml.tmpl --validate yaml -o deployment.yaml
195+
196+
# Validate TOML output
197+
tmpltool Cargo.toml.tmpl --validate toml
184198
```
185199

186200
## Basic Usage

src/cli.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
1-
use clap::Parser;
1+
use clap::{Parser, ValueEnum};
2+
3+
/// Output format for validation
4+
#[derive(Debug, Clone, Copy, ValueEnum)]
5+
pub enum ValidateFormat {
6+
/// Validate as JSON
7+
Json,
8+
/// Validate as YAML
9+
Yaml,
10+
/// Validate as TOML
11+
Toml,
12+
}
213

314
/// A template rendering tool that uses Tera templates with environment variables
415
#[derive(Parser, Debug)]
@@ -16,4 +27,9 @@ pub struct Cli {
1627
/// WARNING: This disables security restrictions. Only use with trusted templates.
1728
#[arg(long)]
1829
pub trust: bool,
30+
31+
/// Validate output format (json, yaml, or toml)
32+
/// If validation fails, the program exits with an error and shows the validation message
33+
#[arg(long, value_enum)]
34+
pub validate: Option<ValidateFormat>,
1935
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub mod context;
1818
pub mod filters;
1919
pub mod functions;
2020
pub mod renderer;
21+
pub mod validator;
2122

2223
pub use cli::Cli;
2324
pub use context::TemplateContext;

src/main.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ use tmpltool::{Cli, render_template};
55
fn main() {
66
let cli = Cli::parse();
77

8-
if let Err(e) = render_template(cli.template.as_deref(), cli.output.as_deref(), cli.trust) {
8+
if let Err(e) = render_template(
9+
cli.template.as_deref(),
10+
cli.output.as_deref(),
11+
cli.trust,
12+
cli.validate,
13+
) {
914
eprintln!("Error: {}", e);
1015
process::exit(1);
1116
}

src/renderer.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{TemplateContext, functions};
1+
use crate::{TemplateContext, cli::ValidateFormat, functions, validator};
22
use minijinja::Environment;
33
use serde::Serialize;
44
use std::fs;
@@ -11,6 +11,7 @@ use std::io::{self, Read, Write};
1111
/// * `template_source` - Optional path to template file. If None, reads from stdin
1212
/// * `output_file` - Optional path to output file. If None, prints to stdout
1313
/// * `trust_mode` - If true, disables filesystem security restrictions
14+
/// * `validate_format` - Optional format to validate output against (JSON, YAML, or TOML)
1415
///
1516
/// # Returns
1617
///
@@ -19,6 +20,7 @@ pub fn render_template(
1920
template_source: Option<&str>,
2021
output_file: Option<&str>,
2122
trust_mode: bool,
23+
validate_format: Option<ValidateFormat>,
2224
) -> Result<(), Box<dyn std::error::Error>> {
2325
// Read template from file or stdin
2426
let template_content = read_template(template_source)?;
@@ -40,6 +42,11 @@ pub fn render_template(
4042
template_context,
4143
)?;
4244

45+
// Validate output if requested
46+
if let Some(format) = validate_format {
47+
validator::validate_output(&rendered, format)?;
48+
}
49+
4350
// Write output to file or stdout
4451
write_output(&rendered, output_file)?;
4552

0 commit comments

Comments
 (0)