diff --git a/packages/html/src/document/mod.rs b/packages/html/src/document/mod.rs
index 27c05c5509..c201004bed 100644
--- a/packages/html/src/document/mod.rs
+++ b/packages/html/src/document/mod.rs
@@ -16,10 +16,23 @@ pub use eval::*;
pub mod head;
pub use head::{Meta, MetaProps, Script, ScriptProps, Style, StyleProps, Title, TitleProps};
+fn format_string_for_js(s: &str) -> String {
+ let escaped = s
+ .replace('\\', "\\\\")
+ .replace('\n', "\\n")
+ .replace('\r', "\\r")
+ .replace('"', "\\\"");
+ format!("\"{escaped}\"")
+}
+
fn format_attributes(attributes: &[(&str, String)]) -> String {
let mut formatted = String::from("[");
for (key, value) in attributes {
- formatted.push_str(&format!("[{key:?}, {value:?}],"));
+ formatted.push_str(&format!(
+ "[{}, {}],",
+ format_string_for_js(key),
+ format_string_for_js(value)
+ ));
}
if formatted.ends_with(',') {
formatted.pop();
@@ -36,9 +49,11 @@ fn create_element_in_head(
let helpers = include_str!("../js/head.js");
let attributes = format_attributes(attributes);
let children = children
- .map(|c| format!("\"{c}\""))
+ .as_deref()
+ .map(format_string_for_js)
.unwrap_or("null".to_string());
- format!(r#"{helpers};window.createElementInHead("{tag}", {attributes}, {children});"#)
+ let tag = format_string_for_js(tag);
+ format!(r#"{helpers};window.createElementInHead({tag}, {attributes}, {children});"#)
}
/// A provider for document-related functionality. By default most methods are driven through [`eval`].