From cc093eda1166ab9026a389a760b2228990d5e88f Mon Sep 17 00:00:00 2001 From: Emil Hultcrantz Date: Thu, 2 Apr 2026 12:50:08 +0200 Subject: [PATCH 1/2] Add HTML safe encoding Fix #64 --- crates/rustwell/src/export/html.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/crates/rustwell/src/export/html.rs b/crates/rustwell/src/export/html.rs index b70343f..0b36b52 100644 --- a/crates/rustwell/src/export/html.rs +++ b/crates/rustwell/src/export/html.rs @@ -119,7 +119,7 @@ impl HtmlExporter { }, self.format_rich_string(slug), if let Some(x) = number { - format!(r#"{x}"#) + format!(r#"{}"#, Self::encode_html(&x)) } else { String::new() }, @@ -197,11 +197,13 @@ impl HtmlExporter { /// Formats a [`RichString`] into a `html`-[String]. fn format_rich_string(&self, str: &RichString) -> String { - str.elements - .iter() - .map(|e| self.format_rich_element(e)) - .collect::>() - .concat() + Self::encode_html( + &str.elements + .iter() + .map(|e| self.format_rich_element(e)) + .collect::>() + .concat(), + ) } /// Formats a [`RichString`] [`rich_string::Element`] into a `html`-[String]. @@ -248,4 +250,11 @@ impl HtmlExporter { DialogueElement::Line(s) => format!(r"

{}

", self.format_rich_string(s)), } } + + /// Encodes potentially dangerous patterns in `html` + fn encode_html(s: &str) -> String { + s.replace('&', "&") + .replace('<', "<") + .replace('>', ">") + } } From c8675bcb35d6473e095a49959a46fa3f4828dc53 Mon Sep 17 00:00:00 2001 From: Emil Hultcrantz Date: Thu, 2 Apr 2026 13:27:43 +0200 Subject: [PATCH 2/2] Fix comments --- crates/rustwell/src/export/html.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/crates/rustwell/src/export/html.rs b/crates/rustwell/src/export/html.rs index 0b36b52..7c5d0ea 100644 --- a/crates/rustwell/src/export/html.rs +++ b/crates/rustwell/src/export/html.rs @@ -119,7 +119,10 @@ impl HtmlExporter { }, self.format_rich_string(slug), if let Some(x) = number { - format!(r#"{}"#, Self::encode_html(&x)) + format!( + r#"{}"#, + Self::encode_special_html_characters(&x) + ) } else { String::new() }, @@ -197,13 +200,11 @@ impl HtmlExporter { /// Formats a [`RichString`] into a `html`-[String]. fn format_rich_string(&self, str: &RichString) -> String { - Self::encode_html( - &str.elements - .iter() - .map(|e| self.format_rich_element(e)) - .collect::>() - .concat(), - ) + str.elements + .iter() + .map(|e| self.format_rich_element(e)) + .collect::>() + .concat() } /// Formats a [`RichString`] [`rich_string::Element`] into a `html`-[String]. @@ -225,7 +226,10 @@ impl HtmlExporter { if element.is_italic() { "" } else { "" }, if element.is_bold() { "" } else { "" }, ); - format!("{prepend}{}{append}", element.text) + format!( + "{prepend}{}{append}", + Self::encode_special_html_characters(&element.text) + ) } /// Formats the [Vec] of the dialogue into a `html`-[String], combining the @@ -252,7 +256,7 @@ impl HtmlExporter { } /// Encodes potentially dangerous patterns in `html` - fn encode_html(s: &str) -> String { + fn encode_special_html_characters(s: &str) -> String { s.replace('&', "&") .replace('<', "<") .replace('>', ">")