use jugar_probar::zero_js::{
DangerousPatternViolation, ZeroJsConfig, ZeroJsValidationResult, ZeroJsValidator,
};
use std::path::PathBuf;
fn main() {
println!("╔══════════════════════════════════════════════════════════════╗");
println!("║ Zero-JS Validation Demo (PROBAR-SPEC-012) ║");
println!("╚══════════════════════════════════════════════════════════════╝");
println!();
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!(" 1. Basic Zero-JS Validation");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!();
let validator = ZeroJsValidator::new();
let default_config = ZeroJsConfig::default();
println!(" Created ZeroJsValidator with default config:");
println!(
" ├─ allow_wasm_inline_scripts: {}",
default_config.allow_wasm_inline_scripts
);
println!(
" ├─ require_manifest: {}",
default_config.require_manifest
);
println!(
" └─ check_dangerous_patterns: {}",
default_config.check_dangerous_patterns
);
println!();
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!(" 2. Configuration Presets");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!();
let strict_config = ZeroJsConfig::strict();
println!(" ZeroJsConfig::strict():");
println!(
" ├─ require_manifest: {}",
strict_config.require_manifest
);
println!(
" ├─ check_dangerous_patterns: {}",
strict_config.check_dangerous_patterns
);
println!(
" └─ allow_wasm_inline_scripts: {}",
strict_config.allow_wasm_inline_scripts
);
println!();
let dev_config = ZeroJsConfig::development();
println!(" ZeroJsConfig::development():");
println!(" ├─ require_manifest: {}", dev_config.require_manifest);
println!(
" ├─ check_dangerous_patterns: {}",
dev_config.check_dangerous_patterns
);
println!(
" └─ allow_wasm_inline_scripts: {}",
dev_config.allow_wasm_inline_scripts
);
println!();
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!(" 3. Dangerous Pattern Detection");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!();
let dangerous_js = r#"
const result = eval('1 + 1');
element.innerHTML = userInput;
new Function('return ' + code)();
document.write('<script>alert(1)</script>');
"#;
let violations = validator.validate_js_content(dangerous_js, std::path::Path::new("test.js"));
println!(
" Detected {} dangerous patterns in test.js:",
violations.len()
);
for (i, v) in violations.iter().enumerate() {
println!(" {}. {}", i + 1, v);
}
println!();
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!(" 4. HTML Inline Script Detection");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!();
let html_with_inline = r#"
<!DOCTYPE html>
<html>
<head>
<script>alert('inline!');</script>
</head>
<body onclick="handleClick()">
<button onmouseover="highlight()">Click me</button>
</body>
</html>
"#;
let strict_validator = ZeroJsValidator::with_config(ZeroJsConfig {
allow_wasm_inline_scripts: false,
..Default::default()
});
let html_violations = strict_validator
.validate_html_content(html_with_inline, std::path::Path::new("index.html"));
println!(
" Detected {} inline script violations:",
html_violations.len()
);
for (i, v) in html_violations.iter().enumerate() {
println!(" {}. {}", i + 1, v);
}
println!();
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!(" 5. WASM-Generated Scripts (Allowed)");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!();
let wasm_html = r#"
<!DOCTYPE html>
<html>
<head>
<script>
// __PROBAR_WASM_GENERATED__
WebAssembly.instantiate(wasmModule).then(instance => {
instance.exports.main();
});
</script>
</head>
<body></body>
</html>
"#;
let default_validator = ZeroJsValidator::new();
let wasm_violations =
default_validator.validate_html_content(wasm_html, std::path::Path::new("wasm.html"));
println!(" WASM-generated scripts with marker comment:");
println!(
" └─ Violations: {} (allowed by default)",
wasm_violations.len()
);
println!();
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!(" 6. Validation Result Display");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!();
let passing_result = ZeroJsValidationResult {
valid: true,
verified_js_files: vec![PathBuf::from("pkg/wasm_bindgen.js")],
..Default::default()
};
println!(" Passing validation:");
println!("{}", indent_string(&format!("{}", passing_result), " "));
println!();
let failing_result = ZeroJsValidationResult {
valid: false,
unauthorized_js_files: vec![PathBuf::from("src/app.js"), PathBuf::from("src/utils.ts")],
forbidden_directories: vec![PathBuf::from("node_modules")],
dangerous_patterns: vec![DangerousPatternViolation {
file: PathBuf::from("src/app.js"),
line: 42,
pattern: "eval(".to_string(),
context: "const x = eval('code')".to_string(),
}],
..Default::default()
};
println!(" Failing validation:");
println!("{}", indent_string(&format!("{}", failing_result), " "));
println!();
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!(" 7. Integration Example");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!();
println!(" Use in your tests:");
println!();
println!(" ```rust");
println!(" use jugar_probar::zero_js::{{ZeroJsValidator, ZeroJsConfig}};");
println!();
println!(" #[test]");
println!(" fn test_wasm_first_compliance() {{");
println!(" let validator = ZeroJsValidator::with_config(");
println!(" ZeroJsConfig::strict()");
println!(" );");
println!();
println!(" let result = validator.validate_directory(\"./pkg\").unwrap();");
println!(" assert!(");
println!(" result.is_valid(),");
println!(" \"Zero-JS validation failed: {{}}\",");
println!(" result");
println!(" );");
println!(" }}");
println!(" ```");
println!();
println!("╔══════════════════════════════════════════════════════════════╗");
println!("║ Demo Complete - WASM-First FTW! ║");
println!("╚══════════════════════════════════════════════════════════════╝");
}
fn indent_string(s: &str, indent: &str) -> String {
s.lines()
.map(|line| format!("{}{}", indent, line))
.collect::<Vec<_>>()
.join("\n")
}