From 55b059e88a02fb5bc1d90ca33df343531db098cc Mon Sep 17 00:00:00 2001 From: Shriyans S Sahoo Date: Tue, 21 Apr 2026 23:00:09 +0530 Subject: [PATCH 1/3] Fixed special charcter escaping --- src/util.rs | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/util.rs b/src/util.rs index a90b83b0..cf9863d2 100644 --- a/src/util.rs +++ b/src/util.rs @@ -179,11 +179,24 @@ pub fn escape_brackets(s: &str) -> String { /// Escape basic html tags and brackets pub fn escape_special_chars(s: &str) -> Cow<'_, str> { - if s.contains('[') { - escape_brackets(s).into() - } else { - s.into() + if !s.contains('[') && !s.contains('&') && !s.contains('<') && !s.contains('>'){ + return s.into(); + } + let mut escaped = s.to_string(); + if escaped.contains('&') { + escaped = escaped.replace('&', "&"); + } + if escaped.contains('<') { + escaped = escaped.replace('<', "<"); } + if escaped.contains('>') { + escaped = escaped.replace('>', ">"); + } + if escaped.contains('[') { + escaped = escape_brackets(&escaped); + } + escaped.into() + } pub fn name_of(maybe_array: &MaybeArray, ignore_group: bool) -> String { @@ -513,3 +526,11 @@ fn pascalcase() { assert_eq!(to_pascal_case("FOO_BAR_1_2"), "FooBar1_2"); assert_eq!(to_pascal_case("FOO_BAR_1_2_"), "FooBar1_2_"); } + +fn test_escape_special_chars(){ + assert_eq!(escape_special_chars("Array[0]"), "Array\\[0\\]"); + assert_eq!(escape_special_chars("Enable & disable"), "Enable & disable"); + assert_eq!(escape_special_chars("Wait<10"), "Wait <10"); + assert_eq!(escape_special_chars("Delay>5"), "Delay >5"); + assert_eq!(escape_special_chars("Flags & [Status] >100"), "Flags & \\[Status\\] > 1"); +} \ No newline at end of file From 6749f3bb40766c46d81e420cc79d6737f77f9941 Mon Sep 17 00:00:00 2001 From: Shriyans S Sahoo Date: Tue, 21 Apr 2026 23:07:24 +0530 Subject: [PATCH 2/3] Fixed special charcter escaping --- src/util.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/util.rs b/src/util.rs index cf9863d2..9caf0dc5 100644 --- a/src/util.rs +++ b/src/util.rs @@ -527,10 +527,15 @@ fn pascalcase() { assert_eq!(to_pascal_case("FOO_BAR_1_2_"), "FooBar1_2_"); } -fn test_escape_special_chars(){ +#[test] +fn test_escape_special_chars() { assert_eq!(escape_special_chars("Array[0]"), "Array\\[0\\]"); assert_eq!(escape_special_chars("Enable & disable"), "Enable & disable"); - assert_eq!(escape_special_chars("Wait<10"), "Wait <10"); - assert_eq!(escape_special_chars("Delay>5"), "Delay >5"); - assert_eq!(escape_special_chars("Flags & [Status] >100"), "Flags & \\[Status\\] > 1"); -} \ No newline at end of file + assert_eq!(escape_special_chars("Wait < 10"), "Wait < 10"); + assert_eq!(escape_special_chars("Delay > 5"), "Delay > 5"); + assert_eq!( + escape_special_chars("Flags & [Status] > 100"), + "Flags & \\[Status\\] > 100" + ); +} + From 10e9addd7111697d97c0204426aaf49756a939d9 Mon Sep 17 00:00:00 2001 From: Shriyans S Sahoo Date: Mon, 27 Apr 2026 21:10:11 +0530 Subject: [PATCH 3/3] Update special character escaping to preserve HTML tags --- src/util.rs | 48 ++++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/src/util.rs b/src/util.rs index 9caf0dc5..151e9f63 100644 --- a/src/util.rs +++ b/src/util.rs @@ -15,6 +15,10 @@ use syn::{ punctuated::Punctuated, token::PathSep, Lit, LitInt, PathArguments, PathSegment, Type, TypePath, }; +use regex::Regex; +use std::sync::OnceLock; + + use anyhow::{anyhow, Result}; pub const BITS_PER_BYTE: u32 = 8; @@ -177,25 +181,34 @@ pub fn escape_brackets(s: &str) -> String { }) } +static TAG_RE: OnceLock = OnceLock::new(); + /// Escape basic html tags and brackets pub fn escape_special_chars(s: &str) -> Cow<'_, str> { - if !s.contains('[') && !s.contains('&') && !s.contains('<') && !s.contains('>'){ + let tag_re= TAG_RE.get_or_init(|| Regex::new(r"<[^>]+>|&[a-zA-Z0-9#]+;").unwrap()); + + if !s.contains('[') && !s.contains('&') && !s.contains('<') && !s.contains('>') { return s.into(); } - let mut escaped = s.to_string(); - if escaped.contains('&') { - escaped = escaped.replace('&', "&"); - } - if escaped.contains('<') { - escaped = escaped.replace('<', "<"); - } - if escaped.contains('>') { - escaped = escaped.replace('>', ">"); + + let mut last_end = 0; + let mut escaped = String::new(); + + for mat in tag_re.find_iter(s) { + let part = &s[last_end..mat.start()]; + escaped.push_str(&part.replace('&', "&").replace('<', "<").replace('>', ">")); + escaped.push_str(mat.as_str()); + last_end = mat.end(); } + let remaining = &s[last_end..]; + + escaped.push_str(&remaining.replace('&', "&").replace('<', "<").replace('>', ">")); + if escaped.contains('[') { - escaped = escape_brackets(&escaped); + escape_brackets(&escaped).into() + } else { + escaped.into() } - escaped.into() } @@ -529,13 +542,12 @@ fn pascalcase() { #[test] fn test_escape_special_chars() { - assert_eq!(escape_special_chars("Array[0]"), "Array\\[0\\]"); + assert_eq!(escape_special_chars("Enable & disable"), "Enable & disable"); assert_eq!(escape_special_chars("Wait < 10"), "Wait < 10"); - assert_eq!(escape_special_chars("Delay > 5"), "Delay > 5"); - assert_eq!( - escape_special_chars("Flags & [Status] > 100"), - "Flags & \\[Status\\] > 100" - ); + assert_eq!(escape_special_chars("This is bold"), "This is bold"); + assert_eq!(escape_special_chars("Use
"), "Use
"); + assert_eq!(escape_special_chars("A & B"), "A & B"); + assert_eq!(escape_special_chars("Array[0]"), "Array\\[0\\]"); }