Skip to content
Twilight React Playground
ثيم رائدaren

stripUnsafeHtml

functionBeginnerserverbrowserlive demo

Removes script-like tags, event handlers and quoted javascript: links from HTML you already trust; it is not a sanitizer for untrusted input.

import { stripUnsafeHtml } from '@salla.sa/twilight-theme-engine/utils';

In plain words

Some Salla translations contain a little HTML, such as <b> around an amount. To show that formatting, React needs dangerouslySetInnerHTML, which inserts HTML exactly as given. stripUnsafeHtml(html) first removes the obvious dangerous parts: <script>, <iframe>, form fields, attributes like onclick="…" and href="javascript:…" links.

It is a quick filter built from regular expressions, not a complete HTML sanitizer. Use it only on HTML from a source you trust, such as Salla's own translations.

Signature

function stripUnsafeHtml(html: string): string

Try it live

A regular-expression filter for HTML you already trust. The result is shown here as text, never rendered.Try this: compare the quoted and the unquoted javascript: link. The unquoted link, the slash before the handler, the encoded link and the style tag all come back unchanged.
Storefront canvas · ar · RTL
input
<p onclick="steal()">Hi</p>
stripUnsafeHtml(input)
<p>Hi</p> (changed)
Controls
What a theme writes
import { useTranslation } from '@salla.sa/twilight-theme-engine/i18n';
import { stripUnsafeHtml } from '@salla.sa/twilight-theme-engine/utils';

// Only for HTML from a trusted source, such as Salla's own translations.
export function FreeShippingAlert() {
  const { t } = useTranslation();
  const html = t('pages.cart.free_shipping_alert').replace(':amount', '50 SAR');
  return <span dangerouslySetInnerHTML={{ __html: stripUnsafeHtml(html) }} />;
}

Example

app/components/cart/FreeShippingAlert.tsx
import { useTranslation } from '@salla.sa/twilight-theme-engine/i18n';
import { stripUnsafeHtml } from '@salla.sa/twilight-theme-engine/utils';

export function FreeShippingAlert({ remaining }: { remaining: string }) {
  const { t } = useTranslation();
  // A Salla translation: "Get <b> a free shipping</b> when you add <b>:amount</b> to cart"
  const html = t('pages.cart.free_shipping_alert').replace(':amount', remaining);
  return <span dangerouslySetInnerHTML={{ __html: stripUnsafeHtml(html) }} />;
}

How it behaves

  • Tags removed, opening and closing: script, iframe, object, embed, form, input, textarea, select, button, link, meta and base, in any letter case. Only the tags go; text between them stays.

  • Attributes removed: any on…= handler preceded by whitespace, with a quoted or unquoted value; and a whole href="javascript:…" or href='javascript:…' attribute.

  • Everything else is kept, <style>, <svg>, <img> and data: URLs included.

  • CartSummary uses it for its free-shipping messages, which come from Salla's translations.

Gotchas

  • It does not make untrusted HTML safe. Checked against the engine's function, these come back unchanged: an unquoted <a href=javascript:…>, a handler after a slash <img/onerror=… src=x>, an entity-encoded href="jav&#x61;script:…", and a <style> block that can restyle the whole page. For text a customer or merchant typed, render it as text instead of HTML.

  • Removing a tag keeps its content: <b>Hi</b><script>steal() becomes <b>Hi</b>steal(), so the script source shows as text.

Related

Source and docs