lib-humus 0.6.0

Helps creating configurable frontends for humans and computers using axum, Tera and toml.
Documentation
// SPDX-FileCopyrightText: 2026 Slatian <baschdel@disroot.org>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

//! This module provides helper functions.

/// Escapes values for use in HTML attributes following the [OWASP recommendations](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#output-encoding-rules-summary)
///
/// This function is inspired by how tera version 1 does its string escapes, i.e. `tera::escape_html`.
pub fn escape_html_attribute(text: &str) -> String {
	let mut output = String::with_capacity(text.len() * 2);
	for c in text.chars() {
		match c {
			'a'..='z' | 'A'..='Z' | '0'..='9' => output.push(c),
			_ => output.push_str(&format!("&#x{:x};", c as u32)),
		}
	}
	output
}

/// Escapes values for use in HTML following the [OWASP recommendations](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#output-encoding-rules-summary)
///
/// This function is inspired by how tera version 1 does its string escapes, i.e. `tera::escape_html`.
pub fn escape_html(text: &str) -> String {
	let mut output = String::with_capacity(text.len() * 2);
	for c in text.chars() {
		match c {
			'&' => output.push_str("&amp;"),
			'<' => output.push_str("&lt;"),
			'>' => output.push_str("&gt;"),
			'"' => output.push_str("&quot;"),
			'\'' => output.push_str("&#x27;"),
			_ => output.push(c),
		}
	}
	output
}

#[cfg(test)]
mod tests {
	use super::*;

	#[test]
	fn test_escape_html_attribute() {
		assert_eq!(
			"ABZabz0123456789",
			escape_html_attribute("ABZabz0123456789")
		);
		assert_eq!("K&#xe4;se", escape_html_attribute("Käse"));
		assert_eq!(
			"&#x3c;script&#x3e;alert&#x28;1&#x29;&#x3c;&#x2f;script&#x3e;",
			escape_html_attribute("<script>alert(1)</script>")
		);
		assert_eq!(
			"test&#x22;&#x3e;foo&#x3c;span&#x20;bar&#x3d;&#x22;",
			escape_html_attribute("test\">foo<span bar=\"")
		);
		assert_eq!(
			"I&#x27;ve&#x20;got&#x20;a&#x20;quote&#x21;",
			escape_html_attribute("I've got a quote!")
		);
	}
}