@particle-academy/react-fancy 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/Action.md CHANGED
@@ -39,7 +39,7 @@ import { Action } from "@particle-academy/react-fancy";
39
39
  | sort | `string` | `"eiab"` | Sort order of decorative elements: `e`=emoji, `i`=icon, `a`=avatar, `b`=badge |
40
40
  | loading | `boolean` | `false` | Show loading spinner (disables the button) |
41
41
  | disabled | `boolean` | - | Disable the button |
42
- | href | `string` | - | Render as an anchor tag instead of a button |
42
+ | href | `string` | - | Render as an anchor tag instead of a button. Sanitized to a safe-protocol allow-list (since v2.5.0) — `javascript:`, `data:`, `vbscript:` are silently dropped and the component renders a `<button>` instead of an `<a>`. |
43
43
 
44
44
  Also extends all native `<button>` HTML attributes (except `color`).
45
45
 
@@ -23,6 +23,29 @@ import { ContentRenderer } from "@particle-academy/react-fancy";
23
23
  | lineSpacing | `number` | `1.6` | Line height |
24
24
  | extensions | `RenderExtension[]` | - | Per-instance render extensions (merged with global) |
25
25
  | className | `string` | - | Additional CSS classes |
26
+ | unsafe | `boolean` | `false` | Skip HTML sanitization. See **Sanitization** below. |
27
+
28
+ ## Sanitization
29
+
30
+ Since v2.5.0, `ContentRenderer` sanitizes its rendered output by default:
31
+
32
+ - Strips `<script>`, `<iframe>`, `<object>`, `<embed>`, `<style>`, `<link>`, `<meta>`, `<base>`, `<form>`.
33
+ - Removes `on*` event-handler attributes (`onclick`, `onerror`, ...).
34
+ - Filters `href`, `src`, `action`, `formaction` to a safe-protocol allow-list (`http`, `https`, `mailto`, `tel`, `sms`, `ftp`, fragment, relative). `javascript:`, `data:`, `vbscript:` are dropped.
35
+
36
+ Pass `unsafe` to opt out — only do this when the input is fully trusted (e.g. your own CMS):
37
+
38
+ ```tsx
39
+ <ContentRenderer value={trustedHtmlFromOurCMS} unsafe />
40
+ ```
41
+
42
+ The helpers are also exported for use elsewhere:
43
+
44
+ ```tsx
45
+ import { sanitizeHtml, sanitizeHref } from "@particle-academy/react-fancy";
46
+ ```
47
+
48
+ > **Render extensions still need to sanitize their own input.** The `content` prop passed to your extension component is the raw text inside the matched tag — treat it as untrusted and call `sanitizeHtml(content)` if you render it as HTML.
26
49
 
27
50
  ## Render Extensions
28
51
 
@@ -31,12 +54,14 @@ Extensions let you define custom tags that are rendered by React components. Reg
31
54
  ```tsx
32
55
  import { registerExtension } from "@particle-academy/react-fancy";
33
56
 
57
+ import { sanitizeHtml } from "@particle-academy/react-fancy";
58
+
34
59
  registerExtension({
35
60
  tag: "thinking",
36
61
  component: ({ content }) => (
37
62
  <details className="bg-zinc-100 p-3 rounded">
38
63
  <summary>Thinking...</summary>
39
- <div dangerouslySetInnerHTML={{ __html: content }} />
64
+ <div dangerouslySetInnerHTML={{ __html: sanitizeHtml(content) }} />
40
65
  </details>
41
66
  ),
42
67
  block: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@particle-academy/react-fancy",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
4
4
  "description": "React UI component library — React port of the fancy-flux Blade component library",
5
5
  "repository": {
6
6
  "type": "git",