This is an automated email from the ASF dual-hosted git repository.

rusackas pushed a commit to branch fix/sqllab-angle-bracket-strings
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 6c2f0a08dc43661b9d75c86d37235c26e2d52369
Author: Evan Rusackas <[email protected]>
AuthorDate: Fri Aug 1 14:35:34 2025 -0700

    fix(sqllab): prevent strings with angle brackets from being hidden
    
    The isProbablyHTML function was incorrectly identifying strings containing 
angle brackets (e.g., "<abcdef:12345>") as HTML, causing them to disappear when 
rendered. This fix improves the HTML detection logic to only recognize known 
HTML tags, preventing false positives for non-HTML strings with angle brackets.
    
    🤖 Generated with [Claude Code](https://claude.ai/code)
    
    Co-Authored-By: Claude <[email protected]>
---
 .../superset-ui-core/src/utils/html.test.tsx       | 15 ++++
 .../packages/superset-ui-core/src/utils/html.tsx   | 80 +++++++++++++++++++++-
 2 files changed, 94 insertions(+), 1 deletion(-)

diff --git 
a/superset-frontend/packages/superset-ui-core/src/utils/html.test.tsx 
b/superset-frontend/packages/superset-ui-core/src/utils/html.test.tsx
index 12a0a4f9f5..e94230de2e 100644
--- a/superset-frontend/packages/superset-ui-core/src/utils/html.test.tsx
+++ b/superset-frontend/packages/superset-ui-core/src/utils/html.test.tsx
@@ -49,6 +49,21 @@ describe('isProbablyHTML', () => {
     const trickyText = 'a <= 10 and b > 10';
     expect(isProbablyHTML(trickyText)).toBe(false);
   });
+
+  it('should return false for strings with angle brackets that are not HTML', 
() => {
+    // Test case from issue #25561
+    expect(isProbablyHTML('<abcdef:12345>')).toBe(false);
+
+    // Other similar cases
+    expect(isProbablyHTML('<foo:bar>')).toBe(false);
+    expect(isProbablyHTML('<123>')).toBe(false);
+    expect(isProbablyHTML('<[email protected]>')).toBe(false);
+    expect(isProbablyHTML('<custom-element>')).toBe(false);
+
+    // Mathematical expressions
+    expect(isProbablyHTML('if x < 5 and y > 10')).toBe(false);
+    expect(isProbablyHTML('price < $100')).toBe(false);
+  });
 });
 
 describe('sanitizeHtmlIfNeeded', () => {
diff --git a/superset-frontend/packages/superset-ui-core/src/utils/html.tsx 
b/superset-frontend/packages/superset-ui-core/src/utils/html.tsx
index 9213fef07f..e151497698 100644
--- a/superset-frontend/packages/superset-ui-core/src/utils/html.tsx
+++ b/superset-frontend/packages/superset-ui-core/src/utils/html.tsx
@@ -68,9 +68,87 @@ export function isProbablyHTML(text: string) {
     return true;
   }
 
+  // Check if the string contains common HTML patterns
+  if (!hasHtmlTagPattern(text)) {
+    return false;
+  }
+
   const parser = new DOMParser();
   const doc = parser.parseFromString(cleanedStr, 'text/html');
-  return Array.from(doc.body.childNodes).some(({ nodeType }) => nodeType === 
1);
+
+  // Check if parsing created actual HTML elements (not just text nodes)
+  const elements = Array.from(doc.body.childNodes).filter(
+    node => node.nodeType === 1,
+  ) as Element[];
+
+  // If no elements were created, it's not HTML
+  if (elements.length === 0) {
+    return false;
+  }
+
+  // Check if the elements are known HTML tags (not custom/unknown tags)
+  // This prevents strings like "<abcdef:12345>" from being treated as HTML
+  return elements.some(element => {
+    const tagName = element.tagName.toLowerCase();
+    // List of common HTML tags we want to recognize
+    const knownHtmlTags = [
+      'div',
+      'span',
+      'p',
+      'a',
+      'b',
+      'i',
+      'u',
+      'em',
+      'strong',
+      'h1',
+      'h2',
+      'h3',
+      'h4',
+      'h5',
+      'h6',
+      'table',
+      'tr',
+      'td',
+      'th',
+      'tbody',
+      'thead',
+      'tfoot',
+      'ul',
+      'ol',
+      'li',
+      'img',
+      'br',
+      'hr',
+      'pre',
+      'code',
+      'blockquote',
+      'section',
+      'article',
+      'nav',
+      'header',
+      'footer',
+      'form',
+      'input',
+      'button',
+      'select',
+      'option',
+      'textarea',
+      'label',
+      'fieldset',
+      'legend',
+      'video',
+      'audio',
+      'canvas',
+      'iframe',
+      'script',
+      'style',
+      'link',
+      'meta',
+      'title',
+    ];
+    return knownHtmlTags.includes(tagName);
+  });
 }
 
 export function sanitizeHtmlIfNeeded(htmlString: string) {

Reply via email to