Skip to content

refactor(code-help): escape snippets centrally instead of in source strings - #8062

Merged
talissoncosta merged 4 commits into
mainfrom
refactor/highlight-escaping
Jul 27, 2026
Merged

refactor(code-help): escape snippets centrally instead of in source strings#8062
talissoncosta merged 4 commits into
mainfrom
refactor/highlight-escaping

Conversation

@talissoncosta

@talissoncosta talissoncosta commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Reviewing this: The bug: Copy Code put HTML entities (<) in the clipboard, because snippet sources were pre-escaped and rendered as raw HTML. Now Highlight escapes everything it renders, once, and the sources are real code. Start with Highlight.js (one line); the snippet files are a mechanical entity-to-bracket swap, safe to skim. The two installs (Java, .NET) are the subtle ones: they escaped at runtime, not in the source.

  • I have read the Contributing Guide.
  • I have added information to docs/ if required so people know about the feature.
  • I have filled in the "Changes" section below.
  • I have filled in the "How did you test this code" section below.

Changes

Split out of #8023 to keep that PR to theming only.

Copy Code was shipping HTML entities (<FlagsmithProvider) to the clipboard: snippet sources were pre-escaped because CodeHelp rendered them as raw HTML. Escape centrally in Highlight instead.

  • Snippet sources store real < > (literal entities removed; Java/.NET drop their runtime Utils.escapeHtml); Highlight always escapes at render, preventEscape is gone.
  • Copy Code now pastes working code; rendering is unchanged from main.
  • The onboarding card's unescape workaround is dead and removed.
  • The prose install notes (curl, Flutter, Rust) drop their <a> tags: the links were already dead on prod (the highlighter strips them) and would have shown as raw markup here; same text, no markup.

How did you test this code?

  • Features page → SDK integration snippet: React shows <FlagsmithProvider>, Java shows the Maven <dependency> XML, .NET shows <PackageReference> (not &lt;)
  • Copy Code on the React and Java snippets, paste into an editor: real brackets, working code
  • Onboarding /getting-started (behind ff onboarding_quickstart_flow): code cards render and copy clean
  • MCP integration page: config snippet renders unchanged
  • Install snippets for curl, Flutter and Rust: prose renders without <a href> markup, same text as prod
  • Flag value editor: a value containing < > still edits and renders (path unchanged, quick sanity)

lint + typecheck pass.

Screenshots

Before (main) After
Java SDK snippet on screen
React snippet pasted into an editor

@vercel

vercel Bot commented Jul 21, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
flagsmith-frontend-preview Ready Ready Preview, Comment Jul 23, 2026 6:33pm
flagsmith-frontend-staging Ready Ready Preview, Comment Jul 23, 2026 6:33pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Ignored Ignored Preview Jul 23, 2026 6:33pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The change makes Highlight always escape rendered content and removes preventEscape from its consumers. Code-help templates now emit literal JSX, TypeScript, and XML syntax instead of HTML entities across React, Next.js, .NET, and Maven examples. Onboarding snippet generation now performs only feature-name substitution. The generated React initialisation example uses useFlags, exposes a named HomePage, renders flag values, and places it inside FlagsmithProvider.

Estimated code review effort: 3 (Moderate) | ~20 minutes


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the front-end Issue related to the React Front End Dashboard label Jul 21, 2026
talissoncosta added a commit that referenced this pull request Jul 21, 2026
Keep this PR theming-only. preventEscape removal + code-help source
de-escaping move to #8062. Highlight keeps embedded + the de-nested
getRawHtml (retaining preventEscape); escaping behaviour is unchanged here.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Zaimwa9
Zaimwa9 previously approved these changes Jul 21, 2026
@talissoncosta
talissoncosta marked this pull request as ready for review July 22, 2026 12:11
@talissoncosta
talissoncosta requested a review from a team as a code owner July 22, 2026 12:11
@talissoncosta
talissoncosta requested review from kyle-ssg and removed request for a team July 22, 2026 12:11
@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Docker builds report

Image Build Status Security report
ghcr.io/flagsmith/flagsmith-api-test:pr-8062 Finished ✅ Skipped
ghcr.io/flagsmith/flagsmith-e2e:pr-8062 Finished ✅ Skipped
ghcr.io/flagsmith/flagsmith-private-cloud:pr-8062 Finished ✅ Results
ghcr.io/flagsmith/flagsmith:pr-8062 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-api:pr-8062 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-frontend:pr-8062 Finished ✅ Results

@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor
✅ private-cloud · depot-ubuntu-latest-16 — run #18683 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  2 passed

Details

stats  2 tests across 2 suites
duration  36.6 seconds
commit  7e217da
info  🔄 Run: #18683 (attempt 1)

🗂️ Previous results
✅ private-cloud · depot-ubuntu-latest-arm-16 — run #18683 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  37.6 seconds
commit  7e217da
info  🔄 Run: #18683 (attempt 1)

✅ oss · depot-ubuntu-latest-arm-16 — run #18683 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  44.7 seconds
commit  7e217da
info  🔄 Run: #18683 (attempt 1)

✅ oss · depot-ubuntu-latest-16 — run #18683 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  32.4 seconds
commit  7e217da
info  🔄 Run: #18683 (attempt 1)

✅ private-cloud · depot-ubuntu-latest-16 — run #18681 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  1 minute, 4 seconds
commit  90b56a6
info  🔄 Run: #18681 (attempt 1)

✅ private-cloud · depot-ubuntu-latest-arm-16 — run #18681 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  2 passed

Details

stats  2 tests across 2 suites
duration  59.8 seconds
commit  90b56a6
info  🔄 Run: #18681 (attempt 1)

✅ oss · depot-ubuntu-latest-arm-16 — run #18681 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  45.6 seconds
commit  90b56a6
info  🔄 Run: #18681 (attempt 1)

✅ oss · depot-ubuntu-latest-16 — run #18681 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  36.3 seconds
commit  90b56a6
info  🔄 Run: #18681 (attempt 1)

✅ private-cloud · depot-ubuntu-latest-arm-16 — run #18680 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  5 passed

Details

stats  5 tests across 5 suites
duration  37.2 seconds
commit  88dd8d4
info  🔄 Run: #18680 (attempt 1)

✅ private-cloud · depot-ubuntu-latest-arm-16 — run #18679 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  3 passed

Details

stats  3 tests across 3 suites
duration  37.4 seconds
commit  0e62939
info  🔄 Run: #18679 (attempt 1)

✅ private-cloud · depot-ubuntu-latest-16 — run #18679 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  3 passed

Details

stats  3 tests across 3 suites
duration  32.9 seconds
commit  0e62939
info  🔄 Run: #18679 (attempt 1)

✅ private-cloud · depot-ubuntu-latest-16 — run #18680 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  3 passed

Details

stats  3 tests across 3 suites
duration  32.4 seconds
commit  88dd8d4
info  🔄 Run: #18680 (attempt 1)

@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Visual Regression

19 screenshots compared. See report for details.
View full report

@talissoncosta

Copy link
Copy Markdown
Contributor Author

@Zaimwa9 can I get a new stamp? I had to rebase it

@talissoncosta
talissoncosta requested a review from Zaimwa9 July 22, 2026 18:48

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/web/components/Highlight.js (1)

106-112: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Include the new render inputs in shouldComponentUpdate.

When disabled changes for an empty snippet, getRawHtml() switches placeholders but the component returns false because the children and tracked state are unchanged. Likewise, changing embedded will not add or remove hljs--embedded. Add both prop comparisons to prevent stale rendering.

Suggested fix
 shouldComponentUpdate(nextProps, nextState) {
+  if (nextProps.disabled !== this.props.disabled) return true
+  if (nextProps.embedded !== this.props.embedded) return true

Also applies to: 163-166


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: aecd899d-7f9d-4747-8746-2cba94f7768a

📥 Commits

Reviewing files that changed from the base of the PR and between 2a4a72c and 33075d5.

📒 Files selected for processing (10)
  • frontend/common/code-help/create-user/create-user-next.js
  • frontend/common/code-help/create-user/create-user-react.js
  • frontend/common/code-help/init/init-next-app-router.js
  • frontend/common/code-help/init/init-next-pages-router.js
  • frontend/common/code-help/init/init-react.js
  • frontend/common/code-help/traits/traits-next.js
  • frontend/common/code-help/traits/traits-react.js
  • frontend/web/components/CodeHelp.tsx
  • frontend/web/components/Highlight.js
  • frontend/web/components/integrations/mcp/MCPSnippet.tsx
💤 Files with no reviewable changes (1)
  • frontend/web/components/CodeHelp.tsx

Comment thread frontend/common/code-help/init/init-react.js
Comment thread frontend/common/code-help/init/init-react.js
talissoncosta and others added 2 commits July 23, 2026 14:20
Highlight now always escapes (dropped the preventEscape branch); MCPSnippet
and CodeHelp no longer pass preventEscape. Code-help sources use raw JSX
(<FlagsmithProvider>) instead of hand-escaped entities (&lt;), so they're
readable. Rendered output is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
They escaped their XML with Utils.escapeHtml at render-build time, which
the entity sweep missed (nothing literal in the source). With Highlight
escaping centrally they double-escaped, showing &lt;dependency&gt; on
screen, and Copy Code shipped entities. The onboarding sdkSnippets
unescape workaround is dead now the sources are clean, so it's gone too.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/common/code-help/create-user/create-user-next.js (1)

26-37: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Import FlagsmithProvider in both generated Next.js templates.

frontend/common/code-help/create-user/create-user-next.js and frontend/common/code-help/traits/traits-next.js both render <FlagsmithProvider> from Option 2 but continue to only import flagsmith plus React hooks, so the emitted examples are missing the provider import and will fail to compile.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 91488edd-9f05-43cf-8705-4535c9113763

📥 Commits

Reviewing files that changed from the base of the PR and between 0e62939 and 88dd8d4.

📒 Files selected for processing (13)
  • frontend/common/code-help/create-user/create-user-next.js
  • frontend/common/code-help/create-user/create-user-react.js
  • frontend/common/code-help/init/init-next-app-router.js
  • frontend/common/code-help/init/init-next-pages-router.js
  • frontend/common/code-help/init/init-react.js
  • frontend/common/code-help/install/install-dotnet.js
  • frontend/common/code-help/install/install-java.js
  • frontend/common/code-help/traits/traits-next.js
  • frontend/common/code-help/traits/traits-react.js
  • frontend/web/components/CodeHelp.tsx
  • frontend/web/components/Highlight.js
  • frontend/web/components/integrations/mcp/MCPSnippet.tsx
  • frontend/web/components/pages/onboarding/OnboardingConnectPanel/sdkSnippets.ts
💤 Files with no reviewable changes (1)
  • frontend/web/components/CodeHelp.tsx

Comment thread frontend/common/code-help/create-user/create-user-react.js
Comment thread frontend/web/components/Highlight.js
Comment thread frontend/common/code-help/install/install-java.js
Highlight is the single escape point now; keeping this helper around
invites pre-escaping content again, the pattern this branch removes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
With Highlight escaping everything, the <a> tags in the curl, Flutter
and Rust install notes showed up as raw markup. The links were already
dead on prod (the highlighter strips the tags) and Copy Code shipped
the markup, so keep the same text prod effectively renders, minus the
tags.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread frontend/common/code-help/install/install-curl.js
Comment thread frontend/common/utils/utils.tsx
@talissoncosta
talissoncosta merged commit 4d5fff8 into main Jul 27, 2026
30 checks passed
@talissoncosta
talissoncosta deleted the refactor/highlight-escaping branch July 27, 2026 14:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

front-end Issue related to the React Front End Dashboard refactor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants