Skip to content

fix(SafeMarkdown): let htmlSchemaOverrides replace matching default attribute rules#42202

Open
rusackas wants to merge 2 commits into
masterfrom
fix/issue-34191-implement-dosu-s-fix-test-first-fix-geto-4
Open

fix(SafeMarkdown): let htmlSchemaOverrides replace matching default attribute rules#42202
rusackas wants to merge 2 commits into
masterfrom
fix/issue-34191-implement-dosu-s-fix-test-first-fix-geto-4

Conversation

@rusackas

Copy link
Copy Markdown
Member

SUMMARY

getOverrideHtmlSchema in SafeMarkdown.tsx merges an operator's htmlSchemaOverrides/HTML_SANITIZATION_SCHEMA_EXTENSIONS into rehype-sanitize's default schema using a mergeWith customizer that concatenates attribute-definition arrays. hast-util-sanitize's findDefinition only ever returns the first definition it finds for a given property name, and the default schema already declares restrictive tuples for some tags, e.g.:

li: [['className', 'task-list-item']],
ul: [...aria, ['className', 'contains-task-list']],
ol: [...aria, ['className', 'contains-task-list']],

So concatenating an operator's override after those defaults never actually widened anything — the restrictive default tuple was always found first. Worse, since a failed allowlist check on className returns [] (an empty array) rather than undefined, hast-util-sanitize's own '*' wildcard fallback never kicked in either. The net effect (see #34191): any CSS class set on <li>/<ul>/<ol> in a Handlebars/Markdown chart gets silently stripped to an empty class="", even with HTML_SANITIZATION_SCHEMA_EXTENSIONS configured to allow it.

This PR changes the merge so that, within attributes, an override definition for a property replaces the default definition for that same property (deduped by property name) instead of just being appended alongside it. Other schema arrays (tagNames, protocols.*, etc.) keep the original concat behavior.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

N/A — this is a schema-merge logic fix with no visual changes on its own; see #34191 for screenshots of the bug (classes on <li>/<ul> being stripped to class="").

TESTING INSTRUCTIONS

Added regression tests in superset-frontend/packages/superset-ui-core/test/components/SafeMarkdown.test.tsx (getOverrideHtmlSchema describe block) that:

  • Pin the bug: with htmlSchemaOverrides: { attributes: { li: ['className'] } }, the merged schema's li definition must be replaced by the override, not have the restrictive default tuple win.
  • Pin the '*' wildcard case: with htmlSchemaOverrides: { attributes: { '*': ['className'] } }, the wildcard override is present, and (documented for clarity) an li-specific default still wins unless li itself is overridden — since findDefinition checks the tag-specific list before '*'.
  • Assert the default task-list className restriction on li/ul/ol is unchanged when no override is supplied.

Manually:

  1. Set HTML_SANITIZATION_SCHEMA_EXTENSIONS = {"attributes": {"li": ["className"]}} (or "*": ["className"] plus a per-tag override) in superset_config.py.
  2. Build a Handlebars or Markdown chart with an <li class="my-class"> element.
  3. Confirm the rendered <li> keeps class="my-class" instead of being stripped to class="".

ADDITIONAL INFORMATION

  • Has associated issue: Fixes Handlebar Chart Styling Does Not Include CSS Class For Lists #34191
  • Required feature flags:
  • Changes UI
  • Includes DB Migration (follow approval process in SIP-59)
    • Migration is atomic, supports rollback & is backwards-compatible
    • Confirm DB migration upgrade and downgrade tested
    • Runtime estimates and downtime expectations provided
  • Introduces new feature or API
  • Removes existing feature or API

…ttribute rules

hast-util-sanitize's findDefinition returns only the first attribute
definition it finds for a given property name, so the previous merge
customizer (which concatenated arrays) left the default schema's
restrictive tuples (e.g. `li: [['className', 'task-list-item']]`) in
charge even after an operator supplied `htmlSchemaOverrides`. Because a
failed allowlist check returns `[]` rather than `undefined`,
hast-util-sanitize's own `'*'` wildcard fallback never kicked in either,
so classes on list elements were silently stripped down to empty
strings regardless of HTML_SANITIZATION_SCHEMA_EXTENSIONS.

getOverrideHtmlSchema now merges each tag's attribute definitions by
property name: an override definition replaces the default definition
for the same property instead of being appended alongside it, so
operator-supplied overrides for li/ul/ol (or '*') actually take effect.

Fixes #34191
@dosubot dosubot Bot added the change:frontend Requires changing the frontend label Jul 18, 2026
@bito-code-review

bito-code-review Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #76f418

Actionable Suggestions - 0
Additional Suggestions - 1
  • superset-frontend/packages/superset-ui-core/test/components/SafeMarkdown.test.tsx - 1
    • Document wildcard override behavior gap · Line 118-130
      This test documents an important edge case: a `'*'` wildcard override does NOT unblock tag-specific defaults. The assertion at line 129 confirms `li` still has its restrictive definition even when `'*'` allows `className`. Consider adding a brief JSDoc to this test describing the practical implication: callers must provide tag-specific overrides to widen restrictions on tags that already have definitions.
Review Details
  • Files reviewed - 2 · Commit Range: 78cc4c6..78cc4c6
    • superset-frontend/packages/superset-ui-core/src/components/SafeMarkdown/SafeMarkdown.tsx
    • superset-frontend/packages/superset-ui-core/test/components/SafeMarkdown.test.tsx
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

Comment thread superset-frontend/packages/superset-ui-core/test/components/SafeMarkdown.test.tsx Outdated
@codecov

codecov Bot commented Jul 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 65.08%. Comparing base (023b60c) to head (a3cccb5).
⚠️ Report is 3 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #42202      +/-   ##
==========================================
- Coverage   65.08%   65.08%   -0.01%     
==========================================
  Files        2758     2758              
  Lines      155229   155242      +13     
  Branches    35572    35575       +3     
==========================================
+ Hits       101026   101033       +7     
- Misses      52288    52294       +6     
  Partials     1915     1915              
Flag Coverage Δ
javascript 70.77% <100.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…isleading test name

Fall back to the default attribute definitions for a tag instead of
throwing when htmlSchemaOverrides.attributes.<tag> isn't an array
(operator-supplied runtime config isn't guaranteed to match the
expected shape). Also fixes a test title that claimed the opposite of
what it asserts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@bito-code-review

bito-code-review Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #284592

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: 78cc4c6..a3cccb5
    • superset-frontend/packages/superset-ui-core/src/components/SafeMarkdown/SafeMarkdown.tsx
    • superset-frontend/packages/superset-ui-core/test/components/SafeMarkdown.test.tsx
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

change:frontend Requires changing the frontend packages size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Handlebar Chart Styling Does Not Include CSS Class For Lists

1 participant