@neeleshyadav/react-native-html-renderer 1.1.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/LICENSE +20 -0
- package/README.md +407 -0
- package/lib/module/HtmlRenderer.js +183 -0
- package/lib/module/HtmlRenderer.js.map +1 -0
- package/lib/module/context/index.js +32 -0
- package/lib/module/context/index.js.map +1 -0
- package/lib/module/hooks/index.js +6 -0
- package/lib/module/hooks/index.js.map +1 -0
- package/lib/module/hooks/useContentWidth.js +12 -0
- package/lib/module/hooks/useContentWidth.js.map +1 -0
- package/lib/module/hooks/useHtmlParser.js +16 -0
- package/lib/module/hooks/useHtmlParser.js.map +1 -0
- package/lib/module/hooks/useTagStyle.js +26 -0
- package/lib/module/hooks/useTagStyle.js.map +1 -0
- package/lib/module/index.js +23 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/parser/index.js +62 -0
- package/lib/module/parser/index.js.map +1 -0
- package/lib/module/renderer/ErrorBoundary.js +66 -0
- package/lib/module/renderer/ErrorBoundary.js.map +1 -0
- package/lib/module/renderer/NodeRenderer.js +279 -0
- package/lib/module/renderer/NodeRenderer.js.map +1 -0
- package/lib/module/renderer/index.js +5 -0
- package/lib/module/renderer/index.js.map +1 -0
- package/lib/module/renderer/tags/BlockTags.js +28 -0
- package/lib/module/renderer/tags/BlockTags.js.map +1 -0
- package/lib/module/renderer/tags/FormTags.js +129 -0
- package/lib/module/renderer/tags/FormTags.js.map +1 -0
- package/lib/module/renderer/tags/ImageTag.js +163 -0
- package/lib/module/renderer/tags/ImageTag.js.map +1 -0
- package/lib/module/renderer/tags/LinkTag.js +50 -0
- package/lib/module/renderer/tags/LinkTag.js.map +1 -0
- package/lib/module/renderer/tags/ListTags.js +96 -0
- package/lib/module/renderer/tags/ListTags.js.map +1 -0
- package/lib/module/renderer/tags/MediaTags.js +69 -0
- package/lib/module/renderer/tags/MediaTags.js.map +1 -0
- package/lib/module/renderer/tags/TableTags.js +48 -0
- package/lib/module/renderer/tags/TableTags.js.map +1 -0
- package/lib/module/renderer/tags/TextTags.js +87 -0
- package/lib/module/renderer/tags/TextTags.js.map +1 -0
- package/lib/module/renderer/tags/index.js +11 -0
- package/lib/module/renderer/tags/index.js.map +1 -0
- package/lib/module/styles/cssToRn.js +34 -0
- package/lib/module/styles/cssToRn.js.map +1 -0
- package/lib/module/styles/darkModeStyles.js +81 -0
- package/lib/module/styles/darkModeStyles.js.map +1 -0
- package/lib/module/styles/defaultStyles.js +218 -0
- package/lib/module/styles/defaultStyles.js.map +1 -0
- package/lib/module/styles/index.js +7 -0
- package/lib/module/styles/index.js.map +1 -0
- package/lib/module/styles/mergeStyles.js +47 -0
- package/lib/module/styles/mergeStyles.js.map +1 -0
- package/lib/module/types/index.js +4 -0
- package/lib/module/types/index.js.map +1 -0
- package/lib/module/utils/accessibility.js +108 -0
- package/lib/module/utils/accessibility.js.map +1 -0
- package/lib/module/utils/cache.js +69 -0
- package/lib/module/utils/cache.js.map +1 -0
- package/lib/module/utils/index.js +95 -0
- package/lib/module/utils/index.js.map +1 -0
- package/lib/module/utils/sanitize.js +102 -0
- package/lib/module/utils/sanitize.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/HtmlRenderer.d.ts +15 -0
- package/lib/typescript/src/HtmlRenderer.d.ts.map +1 -0
- package/lib/typescript/src/context/index.d.ts +5 -0
- package/lib/typescript/src/context/index.d.ts.map +1 -0
- package/lib/typescript/src/hooks/index.d.ts +4 -0
- package/lib/typescript/src/hooks/index.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useContentWidth.d.ts +6 -0
- package/lib/typescript/src/hooks/useContentWidth.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useHtmlParser.d.ts +11 -0
- package/lib/typescript/src/hooks/useHtmlParser.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useTagStyle.d.ts +11 -0
- package/lib/typescript/src/hooks/useTagStyle.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +9 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/parser/index.d.ts +10 -0
- package/lib/typescript/src/parser/index.d.ts.map +1 -0
- package/lib/typescript/src/renderer/ErrorBoundary.d.ts +22 -0
- package/lib/typescript/src/renderer/ErrorBoundary.d.ts.map +1 -0
- package/lib/typescript/src/renderer/NodeRenderer.d.ts +7 -0
- package/lib/typescript/src/renderer/NodeRenderer.d.ts.map +1 -0
- package/lib/typescript/src/renderer/index.d.ts +3 -0
- package/lib/typescript/src/renderer/index.d.ts.map +1 -0
- package/lib/typescript/src/renderer/tags/BlockTags.d.ts +18 -0
- package/lib/typescript/src/renderer/tags/BlockTags.d.ts.map +1 -0
- package/lib/typescript/src/renderer/tags/FormTags.d.ts +16 -0
- package/lib/typescript/src/renderer/tags/FormTags.d.ts.map +1 -0
- package/lib/typescript/src/renderer/tags/ImageTag.d.ts +18 -0
- package/lib/typescript/src/renderer/tags/ImageTag.d.ts.map +1 -0
- package/lib/typescript/src/renderer/tags/LinkTag.d.ts +19 -0
- package/lib/typescript/src/renderer/tags/LinkTag.d.ts.map +1 -0
- package/lib/typescript/src/renderer/tags/ListTags.d.ts +15 -0
- package/lib/typescript/src/renderer/tags/ListTags.d.ts.map +1 -0
- package/lib/typescript/src/renderer/tags/MediaTags.d.ts +14 -0
- package/lib/typescript/src/renderer/tags/MediaTags.d.ts.map +1 -0
- package/lib/typescript/src/renderer/tags/TableTags.d.ts +15 -0
- package/lib/typescript/src/renderer/tags/TableTags.d.ts.map +1 -0
- package/lib/typescript/src/renderer/tags/TextTags.d.ts +22 -0
- package/lib/typescript/src/renderer/tags/TextTags.d.ts.map +1 -0
- package/lib/typescript/src/renderer/tags/index.d.ts +9 -0
- package/lib/typescript/src/renderer/tags/index.d.ts.map +1 -0
- package/lib/typescript/src/styles/cssToRn.d.ts +11 -0
- package/lib/typescript/src/styles/cssToRn.d.ts.map +1 -0
- package/lib/typescript/src/styles/darkModeStyles.d.ts +7 -0
- package/lib/typescript/src/styles/darkModeStyles.d.ts.map +1 -0
- package/lib/typescript/src/styles/defaultStyles.d.ts +8 -0
- package/lib/typescript/src/styles/defaultStyles.d.ts.map +1 -0
- package/lib/typescript/src/styles/index.d.ts +5 -0
- package/lib/typescript/src/styles/index.d.ts.map +1 -0
- package/lib/typescript/src/styles/mergeStyles.d.ts +10 -0
- package/lib/typescript/src/styles/mergeStyles.d.ts.map +1 -0
- package/lib/typescript/src/types/index.d.ts +158 -0
- package/lib/typescript/src/types/index.d.ts.map +1 -0
- package/lib/typescript/src/utils/accessibility.d.ts +32 -0
- package/lib/typescript/src/utils/accessibility.d.ts.map +1 -0
- package/lib/typescript/src/utils/cache.d.ts +24 -0
- package/lib/typescript/src/utils/cache.d.ts.map +1 -0
- package/lib/typescript/src/utils/index.d.ts +33 -0
- package/lib/typescript/src/utils/index.d.ts.map +1 -0
- package/lib/typescript/src/utils/sanitize.d.ts +11 -0
- package/lib/typescript/src/utils/sanitize.d.ts.map +1 -0
- package/package.json +171 -0
- package/src/HtmlRenderer.tsx +216 -0
- package/src/context/index.tsx +30 -0
- package/src/hooks/index.ts +3 -0
- package/src/hooks/useContentWidth.ts +9 -0
- package/src/hooks/useHtmlParser.ts +18 -0
- package/src/hooks/useTagStyle.ts +23 -0
- package/src/index.tsx +39 -0
- package/src/parser/index.ts +80 -0
- package/src/renderer/ErrorBoundary.tsx +80 -0
- package/src/renderer/NodeRenderer.tsx +345 -0
- package/src/renderer/index.tsx +2 -0
- package/src/renderer/tags/BlockTags.tsx +49 -0
- package/src/renderer/tags/FormTags.tsx +169 -0
- package/src/renderer/tags/ImageTag.tsx +215 -0
- package/src/renderer/tags/LinkTag.tsx +76 -0
- package/src/renderer/tags/ListTags.tsx +148 -0
- package/src/renderer/tags/MediaTags.tsx +81 -0
- package/src/renderer/tags/TableTags.tsx +94 -0
- package/src/renderer/tags/TextTags.tsx +139 -0
- package/src/renderer/tags/index.ts +8 -0
- package/src/styles/cssToRn.ts +45 -0
- package/src/styles/darkModeStyles.ts +80 -0
- package/src/styles/defaultStyles.ts +176 -0
- package/src/styles/index.ts +4 -0
- package/src/styles/mergeStyles.ts +59 -0
- package/src/types/index.ts +229 -0
- package/src/utils/accessibility.ts +132 -0
- package/src/utils/cache.ts +83 -0
- package/src/utils/index.ts +151 -0
- package/src/utils/sanitize.ts +149 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Neelesh Yadav
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
# react-native-html-renderer
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/react-native-html-renderer)
|
|
4
|
+
[](https://github.com/Neelesh-FS-Dev/react-native-html-renderer/blob/main/LICENSE)
|
|
5
|
+
[](https://www.typescriptlang.org/)
|
|
6
|
+
[](https://github.com/Neelesh-FS-Dev/react-native-html-renderer/actions/workflows/ci.yml)
|
|
7
|
+
|
|
8
|
+
Renders HTML into 100% native React Native views — actively maintained, TypeScript-first, and lightweight.
|
|
9
|
+
|
|
10
|
+
A modern replacement for the abandoned `react-native-render-html`.
|
|
11
|
+
|
|
12
|
+
## Table of Contents
|
|
13
|
+
|
|
14
|
+
- [Requirements](#requirements)
|
|
15
|
+
- [Installation](#installation)
|
|
16
|
+
- [Basic Usage](#basic-usage)
|
|
17
|
+
- [Props API](#props-api)
|
|
18
|
+
- [Security](#security)
|
|
19
|
+
- [Dark Mode](#dark-mode)
|
|
20
|
+
- [Accessibility](#accessibility)
|
|
21
|
+
- [Font Scaling](#font-scaling)
|
|
22
|
+
- [Supported HTML Tags](#supported-html-tags)
|
|
23
|
+
- [Custom Renderers](#custom-renderers)
|
|
24
|
+
- [Tag & Class Styles](#tag--class-styles)
|
|
25
|
+
- [Hooks](#hooks)
|
|
26
|
+
- [Utility Exports](#utility-exports)
|
|
27
|
+
- [Image Handling](#image-handling)
|
|
28
|
+
- [Debug Mode](#debug-mode)
|
|
29
|
+
- [Limitations](#limitations)
|
|
30
|
+
- [Migration from react-native-render-html v6](#migration-from-react-native-render-html-v6)
|
|
31
|
+
- [Contributing](#contributing)
|
|
32
|
+
- [License](#license)
|
|
33
|
+
|
|
34
|
+
## Requirements
|
|
35
|
+
|
|
36
|
+
| Dependency | Version |
|
|
37
|
+
| ------------- | --------- |
|
|
38
|
+
| React | >= 18.0.0 |
|
|
39
|
+
| React Native | >= 0.71.0 |
|
|
40
|
+
| Node.js | >= 20 |
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
npm install react-native-html-renderer
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
or
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
yarn add react-native-html-renderer
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
All other dependencies (`htmlparser2`, `css-to-react-native`) are bundled — no extra installs needed.
|
|
55
|
+
|
|
56
|
+
## Basic Usage
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
import { HtmlRenderer } from 'react-native-html-renderer';
|
|
60
|
+
import { useWindowDimensions, Linking } from 'react-native';
|
|
61
|
+
|
|
62
|
+
function MyComponent() {
|
|
63
|
+
const { width } = useWindowDimensions();
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<HtmlRenderer
|
|
67
|
+
html="<h1>Hello</h1><p>This is <strong>bold</strong> and <em>italic</em>.</p>"
|
|
68
|
+
contentWidth={width - 32}
|
|
69
|
+
onLinkPress={(href) => Linking.openURL(href)}
|
|
70
|
+
/>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Props API
|
|
76
|
+
|
|
77
|
+
| Prop | Type | Default | Description |
|
|
78
|
+
| ---- | ---- | ------- | ----------- |
|
|
79
|
+
| `html` | `string` | *required* | Raw HTML string to render |
|
|
80
|
+
| `contentWidth` | `number` | *required* | Available width for layout and image scaling |
|
|
81
|
+
| `baseStyle` | `ViewStyle` | `undefined` | Style applied to the root container |
|
|
82
|
+
| `tagsStyles` | `Record<string, RNStyle>` | `undefined` | Per-tag style overrides |
|
|
83
|
+
| `classesStyles` | `Record<string, RNStyle>` | `undefined` | Styles applied by HTML class name |
|
|
84
|
+
| `idsStyles` | `Record<string, RNStyle>` | `undefined` | Styles applied by HTML element id |
|
|
85
|
+
| `customRenderers` | `Record<string, CustomRenderer>` | `undefined` | Override rendering for specific tags |
|
|
86
|
+
| `onLinkPress` | `(href, attrs) => void` | `undefined` | Callback for `<a>` tag taps |
|
|
87
|
+
| `onImagePress` | `(src, attrs) => void` | `undefined` | Callback for image taps |
|
|
88
|
+
| `onError` | `(error: Error) => void` | `undefined` | Called on parse or render errors |
|
|
89
|
+
| `fallback` | `ReactNode` | default message | Custom UI to show when an error occurs |
|
|
90
|
+
| `ignoredTags` | `string[]` | `undefined` | Tags to completely skip (including children) |
|
|
91
|
+
| `ignoredStyles` | `string[]` | `undefined` | CSS property names to ignore |
|
|
92
|
+
| `allowedStyles` | `string[]` | `undefined` | Whitelist of CSS properties to allow |
|
|
93
|
+
| `defaultTextProps` | `TextProps` | `undefined` | Default props for all `<Text>` components |
|
|
94
|
+
| `defaultViewProps` | `ViewProps` | `undefined` | Default props for all `<View>` components |
|
|
95
|
+
| `renderersProps` | `Record<string, object>` | `undefined` | Extra props for specific tag renderers |
|
|
96
|
+
| `maxImagesWidth` | `number` | `undefined` | Maximum image width cap |
|
|
97
|
+
| `imagesInitialDimensions` | `{ width, height }` | `{100, 100}` | Placeholder size before image loads |
|
|
98
|
+
| `listsPrefixesRenderers` | `ListsPrefixesRenderers` | `undefined` | Custom bullet/number components |
|
|
99
|
+
| `emSize` | `number` | `14` | Base em unit in pixels |
|
|
100
|
+
| `systemFonts` | `string[]` | `undefined` | Available system fonts |
|
|
101
|
+
| `fallbackFonts` | `Record<string, string>` | `undefined` | Map unsupported fonts to fallbacks |
|
|
102
|
+
| `debug` | `boolean` | `false` | Log DOM, styles, and show red debug borders |
|
|
103
|
+
| `allowDangerousHtml` | `boolean` | `false` | When false, strips dangerous tags and attributes |
|
|
104
|
+
| `darkModeStyles` | `Record<string, RNStyle>` | `undefined` | Per-tag overrides applied in dark mode |
|
|
105
|
+
| `colorScheme` | `'light' \| 'dark'` | system | Override color scheme detection |
|
|
106
|
+
| `allowFontScaling` | `boolean` | `true` | Allow system font-size accessibility scaling |
|
|
107
|
+
| `maxFontSizeMultiplier` | `number` | `undefined` | Cap the font-size multiplier |
|
|
108
|
+
|
|
109
|
+
## Security
|
|
110
|
+
|
|
111
|
+
By default (when `allowDangerousHtml` is `false`), the renderer automatically:
|
|
112
|
+
|
|
113
|
+
- Strips `<script>`, `<iframe>`, `<object>`, `<embed>`, `<form>`, `<svg>`, `<math>` tags
|
|
114
|
+
- Neutralizes `javascript:`, `vbscript:`, and `data:text/html` URLs
|
|
115
|
+
- Removes all event handler attributes (`onclick`, `onerror`, `onload`, etc.)
|
|
116
|
+
- Guards against prototype pollution and deeply nested DOM attacks
|
|
117
|
+
|
|
118
|
+
Set `allowDangerousHtml={true}` to opt out of sanitization. See [SECURITY.md](SECURITY.md) for details.
|
|
119
|
+
|
|
120
|
+
## Dark Mode
|
|
121
|
+
|
|
122
|
+
The renderer automatically detects the system color scheme and applies dark-mode-aware default styles. You can add per-tag overrides:
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
<HtmlRenderer
|
|
126
|
+
html={html}
|
|
127
|
+
contentWidth={width}
|
|
128
|
+
darkModeStyles={{
|
|
129
|
+
p: { color: '#ddd' },
|
|
130
|
+
pre: { backgroundColor: '#1a1a2e', color: '#eee' },
|
|
131
|
+
}}
|
|
132
|
+
/>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Override detection with the `colorScheme` prop: `colorScheme="dark"` or `colorScheme="light"`.
|
|
136
|
+
|
|
137
|
+
Use `getDefaultDarkModeStyles()` to inspect the built-in dark mode defaults.
|
|
138
|
+
|
|
139
|
+
## Accessibility
|
|
140
|
+
|
|
141
|
+
All interactive elements include proper accessibility attributes:
|
|
142
|
+
|
|
143
|
+
- `<a>` → `accessibilityRole="link"`, `accessibilityHint="Opens {href}"`
|
|
144
|
+
- `<img>` → `accessibilityRole="image"`, `accessibilityLabel` from `alt`
|
|
145
|
+
- `<button>` → `accessibilityRole="button"`
|
|
146
|
+
- `<h1>`–`<h6>` → `accessibilityRole="header"`
|
|
147
|
+
- `<ul>`/`<ol>` → `accessibilityRole="list"`
|
|
148
|
+
- `<input type="checkbox">` → `accessibilityRole="checkbox"`, `accessibilityState.checked`
|
|
149
|
+
|
|
150
|
+
HTML `aria-*` attributes are mapped to React Native equivalents:
|
|
151
|
+
|
|
152
|
+
```html
|
|
153
|
+
<p aria-label="Custom label">Accessible paragraph</p>
|
|
154
|
+
<span aria-hidden="true">Hidden from screen readers</span>
|
|
155
|
+
<button aria-disabled="true">Disabled button</button>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
| HTML attribute | React Native equivalent |
|
|
159
|
+
| -------------- | ---------------------- |
|
|
160
|
+
| `aria-label` | `accessibilityLabel` |
|
|
161
|
+
| `aria-hidden="true"` | `accessible={false}` |
|
|
162
|
+
| `aria-disabled` | `accessibilityState.disabled` |
|
|
163
|
+
| `aria-checked` | `accessibilityState.checked` |
|
|
164
|
+
| `aria-expanded` | `accessibilityState.expanded` |
|
|
165
|
+
| `aria-busy` | `accessibilityState.busy` |
|
|
166
|
+
| `aria-role` / `role` | `accessibilityRole` |
|
|
167
|
+
|
|
168
|
+
## Font Scaling
|
|
169
|
+
|
|
170
|
+
Respects system accessibility font-size settings:
|
|
171
|
+
|
|
172
|
+
```tsx
|
|
173
|
+
<HtmlRenderer
|
|
174
|
+
html={html}
|
|
175
|
+
contentWidth={width}
|
|
176
|
+
allowFontScaling={true}
|
|
177
|
+
maxFontSizeMultiplier={1.5}
|
|
178
|
+
/>
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Supported HTML Tags
|
|
182
|
+
|
|
183
|
+
### Block Elements
|
|
184
|
+
|
|
185
|
+
`<div>`, `<section>`, `<article>`, `<header>`, `<footer>`, `<main>`, `<nav>`, `<aside>`, `<blockquote>`, `<pre>`, `<figure>`
|
|
186
|
+
|
|
187
|
+
### Text Elements
|
|
188
|
+
|
|
189
|
+
`<p>`, `<h1>`-`<h6>`, `<span>`, `<strong>`, `<b>`, `<em>`, `<i>`, `<u>`, `<s>`, `<strike>`, `<del>`, `<ins>`, `<mark>`, `<small>`, `<sub>`, `<sup>`, `<code>`, `<label>`
|
|
190
|
+
|
|
191
|
+
### Media
|
|
192
|
+
|
|
193
|
+
`<img>` (with auto-sizing, caching, loading state, error fallback), `<video>` and `<audio>` (placeholder views)
|
|
194
|
+
|
|
195
|
+
### Lists
|
|
196
|
+
|
|
197
|
+
`<ul>`, `<ol>`, `<li>` with proper bullets/numbers and nested list support
|
|
198
|
+
|
|
199
|
+
### Tables
|
|
200
|
+
|
|
201
|
+
`<table>`, `<thead>`, `<tbody>`, `<tfoot>`, `<tr>`, `<th>`, `<td>` wrapped in horizontal ScrollView
|
|
202
|
+
|
|
203
|
+
### Links
|
|
204
|
+
|
|
205
|
+
`<a>` with `onLinkPress` callback
|
|
206
|
+
|
|
207
|
+
### Forms (read-only)
|
|
208
|
+
|
|
209
|
+
`<input>`, `<textarea>`, `<button>`, `<select>` rendered as visual read-only elements
|
|
210
|
+
|
|
211
|
+
### Self-closing
|
|
212
|
+
|
|
213
|
+
`<br>`, `<hr>`
|
|
214
|
+
|
|
215
|
+
### Silently Ignored
|
|
216
|
+
|
|
217
|
+
`<script>`, `<style>`, `<head>`, `<meta>`, `<link>`, `<title>`, `<noscript>`
|
|
218
|
+
|
|
219
|
+
### Unknown Tags
|
|
220
|
+
|
|
221
|
+
Unknown tags render their children without crashing. In `debug` mode, a warning is logged.
|
|
222
|
+
|
|
223
|
+
## Custom Renderers
|
|
224
|
+
|
|
225
|
+
Override how any tag renders:
|
|
226
|
+
|
|
227
|
+
```tsx
|
|
228
|
+
import { HtmlRenderer } from 'react-native-html-renderer';
|
|
229
|
+
import type { CustomRendererProps } from 'react-native-html-renderer';
|
|
230
|
+
import { View } from 'react-native';
|
|
231
|
+
|
|
232
|
+
function myBlockquote({ children, style }: CustomRendererProps) {
|
|
233
|
+
return (
|
|
234
|
+
<View style={{ borderLeftWidth: 4, borderLeftColor: '#3498db', paddingLeft: 12 }}>
|
|
235
|
+
{children}
|
|
236
|
+
</View>
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
<HtmlRenderer
|
|
241
|
+
html="<blockquote><p>Quoted text</p></blockquote>"
|
|
242
|
+
contentWidth={350}
|
|
243
|
+
customRenderers={{ blockquote: myBlockquote }}
|
|
244
|
+
/>
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
The `CustomRendererProps` object includes:
|
|
248
|
+
|
|
249
|
+
| Property | Type | Description |
|
|
250
|
+
| -------- | ---- | ----------- |
|
|
251
|
+
| `node` | `DOMElement` | The parsed DOM element |
|
|
252
|
+
| `children` | `ReactNode[]` | Pre-rendered child nodes |
|
|
253
|
+
| `style` | `RNStyle` | Merged style for the element |
|
|
254
|
+
| `attributes` | `Record<string, string>` | HTML attributes |
|
|
255
|
+
| `passProps` | `Record<string, unknown>` | Extra props from `renderersProps` |
|
|
256
|
+
| `renderChildren` | `(nodes: DOMNode[]) => ReactNode[]` | Helper to render child DOM nodes |
|
|
257
|
+
| `contentWidth` | `number` | Available content width |
|
|
258
|
+
|
|
259
|
+
## Tag & Class Styles
|
|
260
|
+
|
|
261
|
+
```tsx
|
|
262
|
+
<HtmlRenderer
|
|
263
|
+
html='<p class="intro">Hello</p><p id="note">Note</p>'
|
|
264
|
+
contentWidth={350}
|
|
265
|
+
tagsStyles={{
|
|
266
|
+
p: { fontSize: 16, lineHeight: 24 },
|
|
267
|
+
h1: { color: '#2c3e50' },
|
|
268
|
+
}}
|
|
269
|
+
classesStyles={{
|
|
270
|
+
intro: { backgroundColor: '#f0f0f0', padding: 8 },
|
|
271
|
+
}}
|
|
272
|
+
idsStyles={{
|
|
273
|
+
note: { fontStyle: 'italic', color: '#999' },
|
|
274
|
+
}}
|
|
275
|
+
/>
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Style cascade order: **default tag style** → **tagsStyles** → **classesStyles** → **idsStyles** → **inline style**
|
|
279
|
+
|
|
280
|
+
In dark mode: **default dark styles** and **darkModeStyles** are merged into the tag styles layer.
|
|
281
|
+
|
|
282
|
+
## Hooks
|
|
283
|
+
|
|
284
|
+
Three reusable hooks exported for use inside custom renderers or elsewhere:
|
|
285
|
+
|
|
286
|
+
```tsx
|
|
287
|
+
import { useHtmlParser, useContentWidth, useTagStyle } from 'react-native-html-renderer';
|
|
288
|
+
|
|
289
|
+
// Parse HTML into a DOM tree
|
|
290
|
+
const nodes = useHtmlParser('<p>Hello</p>');
|
|
291
|
+
|
|
292
|
+
// Get contentWidth from the nearest HtmlRenderer context
|
|
293
|
+
const width = useContentWidth();
|
|
294
|
+
|
|
295
|
+
// Get the resolved style for a tag from context
|
|
296
|
+
const pStyle = useTagStyle('p');
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
## Utility Exports
|
|
300
|
+
|
|
301
|
+
```tsx
|
|
302
|
+
import {
|
|
303
|
+
parseHTML,
|
|
304
|
+
parseInlineStyle,
|
|
305
|
+
getDefaultTagStyles,
|
|
306
|
+
getDefaultDarkModeStyles,
|
|
307
|
+
sanitizeDOM,
|
|
308
|
+
clearDOMCache,
|
|
309
|
+
clearImageDimensionCache,
|
|
310
|
+
} from 'react-native-html-renderer';
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
| Export | Description |
|
|
314
|
+
| ------ | ----------- |
|
|
315
|
+
| `parseHTML(html, ignoredTags?)` | Parse an HTML string into a `DOMNode[]` tree |
|
|
316
|
+
| `parseInlineStyle(css, ignored?, allowed?)` | Convert a CSS string to a React Native style object |
|
|
317
|
+
| `getDefaultTagStyles(emSize)` | Get the default styles for all supported tags |
|
|
318
|
+
| `getDefaultDarkModeStyles()` | Get the built-in dark mode style overrides |
|
|
319
|
+
| `sanitizeDOM(nodes)` | Strip dangerous tags, attributes, and URLs from a DOM tree |
|
|
320
|
+
| `clearDOMCache()` | Clear the parsed DOM LRU cache (max 50 entries) |
|
|
321
|
+
| `clearImageDimensionCache()` | Clear the image dimension LRU cache (max 200 entries) |
|
|
322
|
+
|
|
323
|
+
## Image Handling
|
|
324
|
+
|
|
325
|
+
Images automatically:
|
|
326
|
+
|
|
327
|
+
- Fetch dimensions via `Image.getSize()` for remote URLs
|
|
328
|
+
- **Cache dimensions** after first fetch to avoid repeated network calls
|
|
329
|
+
- Scale proportionally to fit `contentWidth`
|
|
330
|
+
- Respect `maxImagesWidth` cap
|
|
331
|
+
- Show a loading indicator while fetching
|
|
332
|
+
- Show an error fallback if loading fails
|
|
333
|
+
- Support `onImagePress` callback
|
|
334
|
+
- Support `data:` base64 URIs
|
|
335
|
+
|
|
336
|
+
## Error Handling
|
|
337
|
+
|
|
338
|
+
The renderer handles errors at multiple levels to ensure it never crashes your app:
|
|
339
|
+
|
|
340
|
+
- **Parse errors** — malformed HTML is caught during parsing; returns empty output and calls `onError`
|
|
341
|
+
- **Render errors** — if a node fails to render, it is skipped (other nodes continue rendering)
|
|
342
|
+
- **Custom renderer errors** — exceptions in user-provided `customRenderers` are caught per-node; the failing tag is skipped with a debug-mode console error
|
|
343
|
+
- **Style errors** — invalid inline CSS is silently ignored
|
|
344
|
+
- **Image errors** — failed image loads show a fallback placeholder
|
|
345
|
+
- **React ErrorBoundary** — wraps the entire tree as a final safety net
|
|
346
|
+
|
|
347
|
+
```tsx
|
|
348
|
+
<HtmlRenderer
|
|
349
|
+
html={html}
|
|
350
|
+
contentWidth={width}
|
|
351
|
+
onError={(error) => {
|
|
352
|
+
// Log to your error tracking service
|
|
353
|
+
Sentry.captureException(error);
|
|
354
|
+
}}
|
|
355
|
+
fallback={<Text>Something went wrong.</Text>}
|
|
356
|
+
/>
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
In `debug` mode, all caught errors are logged to the console with the tag name and stack trace.
|
|
360
|
+
|
|
361
|
+
## Debug Mode
|
|
362
|
+
|
|
363
|
+
Set `debug={true}` to enable:
|
|
364
|
+
|
|
365
|
+
- Parsed DOM tree logged to console
|
|
366
|
+
- Computed styles per node logged to console
|
|
367
|
+
- Unknown/skipped tags logged as warnings
|
|
368
|
+
- Red border drawn around every rendered node
|
|
369
|
+
- Color scheme logged to console
|
|
370
|
+
|
|
371
|
+
## Limitations
|
|
372
|
+
|
|
373
|
+
- **Form elements are read-only** — `<input>`, `<textarea>`, `<select>`, `<button>` render as visual representations but are not interactive
|
|
374
|
+
- **Video and audio are placeholders** — `<video>` and `<audio>` render placeholder views, not playable media (use custom renderers to integrate a media player)
|
|
375
|
+
- **No CSS cascade beyond inline** — only inline `style` attributes, tag/class/id overrides, and default styles are supported (no external stylesheets, no `<style>` blocks)
|
|
376
|
+
- **Limited CSS properties** — only properties supported by React Native's style system are converted (see `css-to-react-native` for the full list)
|
|
377
|
+
- **No CSS animations or transitions**
|
|
378
|
+
- **No web component support** (`<slot>`, `<template>`, shadow DOM)
|
|
379
|
+
- **Tables may overflow** — wide tables are wrapped in a horizontal `ScrollView`
|
|
380
|
+
|
|
381
|
+
## Migration from [react-native-render-html](https://github.com/meliorence/react-native-render-html) v6
|
|
382
|
+
|
|
383
|
+
| react-native-render-html | react-native-html-renderer |
|
|
384
|
+
| ------------------------ | -------------------------- |
|
|
385
|
+
| `<RenderHtml source={{ html }} />` | `<HtmlRenderer html={html} contentWidth={width} />` |
|
|
386
|
+
| `renderers={{ p: PRenderer }}` | `customRenderers={{ p: myPRenderer }}` |
|
|
387
|
+
| `tagsStyles={{ p: { ... } }}` | `tagsStyles={{ p: { ... } }}` (same API) |
|
|
388
|
+
| `classesStyles={{ ... }}` | `classesStyles={{ ... }}` (same API) |
|
|
389
|
+
| `ignoredDomTags={[...]}` | `ignoredTags={[...]}` |
|
|
390
|
+
| `renderersProps={{ a: { ... } }}` | `renderersProps={{ a: { ... } }}` (same API) |
|
|
391
|
+
| `systemFonts={[...]}` | `systemFonts={[...]}` (same API) |
|
|
392
|
+
| `defaultTextProps={{ ... }}` | `defaultTextProps={{ ... }}` (same API) |
|
|
393
|
+
| *(no equivalent)* | `allowDangerousHtml` — built-in XSS sanitization |
|
|
394
|
+
| *(no equivalent)* | `darkModeStyles` — automatic dark mode support |
|
|
395
|
+
| *(no equivalent)* | `allowFontScaling` / `maxFontSizeMultiplier` |
|
|
396
|
+
|
|
397
|
+
## Contributing
|
|
398
|
+
|
|
399
|
+
See the [contributing guide](CONTRIBUTING.md) for development workflow and pull request instructions.
|
|
400
|
+
|
|
401
|
+
## License
|
|
402
|
+
|
|
403
|
+
MIT
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import { View, useColorScheme } from 'react-native';
|
|
5
|
+
import { HtmlRendererContext } from "./context/index.js";
|
|
6
|
+
import { parseHTML } from "./parser/index.js";
|
|
7
|
+
import { getDefaultDarkModeStyles } from "./styles/darkModeStyles.js";
|
|
8
|
+
import { renderNodes } from "./renderer/index.js";
|
|
9
|
+
import { ErrorBoundary } from "./renderer/ErrorBoundary.js";
|
|
10
|
+
import { sanitizeDOM } from "./utils/sanitize.js";
|
|
11
|
+
import { getCachedDOM, setCachedDOM, buildDOMCacheKey } from "./utils/cache.js";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Renders an HTML string into native React Native components.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* <HtmlRenderer
|
|
19
|
+
* html="<h1>Hello</h1><p>World</p>"
|
|
20
|
+
* contentWidth={350}
|
|
21
|
+
* onLinkPress={(href) => Linking.openURL(href)}
|
|
22
|
+
* />
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
26
|
+
export function HtmlRenderer({
|
|
27
|
+
html,
|
|
28
|
+
contentWidth,
|
|
29
|
+
baseStyle,
|
|
30
|
+
tagsStyles,
|
|
31
|
+
classesStyles,
|
|
32
|
+
idsStyles,
|
|
33
|
+
customRenderers,
|
|
34
|
+
onLinkPress,
|
|
35
|
+
onImagePress,
|
|
36
|
+
onError,
|
|
37
|
+
fallback,
|
|
38
|
+
ignoredTags,
|
|
39
|
+
ignoredStyles,
|
|
40
|
+
allowedStyles,
|
|
41
|
+
defaultTextProps,
|
|
42
|
+
defaultViewProps,
|
|
43
|
+
renderersProps,
|
|
44
|
+
maxImagesWidth,
|
|
45
|
+
imagesInitialDimensions,
|
|
46
|
+
listsPrefixesRenderers,
|
|
47
|
+
emSize = 14,
|
|
48
|
+
systemFonts,
|
|
49
|
+
fallbackFonts,
|
|
50
|
+
debug = false,
|
|
51
|
+
allowDangerousHtml = false,
|
|
52
|
+
darkModeStyles,
|
|
53
|
+
colorScheme: colorSchemeProp,
|
|
54
|
+
allowFontScaling = true,
|
|
55
|
+
maxFontSizeMultiplier
|
|
56
|
+
}) {
|
|
57
|
+
// --- Color scheme ---
|
|
58
|
+
const systemScheme = useColorScheme();
|
|
59
|
+
const resolvedScheme = colorSchemeProp ?? systemScheme;
|
|
60
|
+
const isDark = resolvedScheme === 'dark';
|
|
61
|
+
|
|
62
|
+
// --- Memoize set conversions ---
|
|
63
|
+
const ignoredTagsSet = useMemo(() => new Set(ignoredTags ?? []), [ignoredTags]);
|
|
64
|
+
const ignoredStylesSet = useMemo(() => new Set(ignoredStyles ?? []), [ignoredStyles]);
|
|
65
|
+
const allowedStylesSet = useMemo(() => allowedStyles ? new Set(allowedStyles) : null, [allowedStyles]);
|
|
66
|
+
|
|
67
|
+
// --- Parse DOM (with cache, key includes sanitization params to prevent poisoning) ---
|
|
68
|
+
const nodes = useMemo(() => {
|
|
69
|
+
try {
|
|
70
|
+
const cacheKey = buildDOMCacheKey(html, allowDangerousHtml, ignoredTagsSet);
|
|
71
|
+
const cached = getCachedDOM(cacheKey);
|
|
72
|
+
if (cached) return cached;
|
|
73
|
+
let parsed = parseHTML(html, ignoredTagsSet);
|
|
74
|
+
|
|
75
|
+
// Sanitize if not explicitly opted out
|
|
76
|
+
if (!allowDangerousHtml) {
|
|
77
|
+
parsed = sanitizeDOM(parsed);
|
|
78
|
+
}
|
|
79
|
+
setCachedDOM(cacheKey, parsed);
|
|
80
|
+
return parsed;
|
|
81
|
+
} catch (e) {
|
|
82
|
+
const error = e instanceof Error ? e : new Error('Failed to parse HTML');
|
|
83
|
+
if (debug) {
|
|
84
|
+
console.error('[HtmlRenderer] Parse error:', error);
|
|
85
|
+
}
|
|
86
|
+
onError?.(error);
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
}, [html, ignoredTagsSet, allowDangerousHtml, debug, onError]);
|
|
90
|
+
|
|
91
|
+
// --- Merge dark mode styles ---
|
|
92
|
+
const effectiveTagsStyles = useMemo(() => {
|
|
93
|
+
const base = tagsStyles ?? {};
|
|
94
|
+
if (!isDark) return base;
|
|
95
|
+
const defaultDark = getDefaultDarkModeStyles();
|
|
96
|
+
const userDark = darkModeStyles ?? {};
|
|
97
|
+
|
|
98
|
+
// Merge: base tagsStyles + default dark overrides + user dark overrides
|
|
99
|
+
const merged = {
|
|
100
|
+
...base
|
|
101
|
+
};
|
|
102
|
+
for (const tag of Object.keys(defaultDark)) {
|
|
103
|
+
merged[tag] = {
|
|
104
|
+
...(merged[tag] ?? {}),
|
|
105
|
+
...defaultDark[tag]
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
for (const tag of Object.keys(userDark)) {
|
|
109
|
+
merged[tag] = {
|
|
110
|
+
...(merged[tag] ?? {}),
|
|
111
|
+
...userDark[tag]
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
return merged;
|
|
115
|
+
}, [tagsStyles, isDark, darkModeStyles]);
|
|
116
|
+
|
|
117
|
+
// --- Build context value ---
|
|
118
|
+
const ctx = useMemo(() => ({
|
|
119
|
+
contentWidth,
|
|
120
|
+
tagsStyles: effectiveTagsStyles,
|
|
121
|
+
classesStyles: classesStyles ?? {},
|
|
122
|
+
idsStyles: idsStyles ?? {},
|
|
123
|
+
customRenderers: customRenderers ?? {},
|
|
124
|
+
onLinkPress,
|
|
125
|
+
onImagePress,
|
|
126
|
+
renderersProps: renderersProps ?? {},
|
|
127
|
+
emSize,
|
|
128
|
+
debug,
|
|
129
|
+
ignoredTags: ignoredTagsSet,
|
|
130
|
+
ignoredStyles: ignoredStylesSet,
|
|
131
|
+
allowedStyles: allowedStylesSet,
|
|
132
|
+
defaultTextProps,
|
|
133
|
+
defaultViewProps,
|
|
134
|
+
maxImagesWidth,
|
|
135
|
+
imagesInitialDimensions: imagesInitialDimensions ?? {
|
|
136
|
+
width: 100,
|
|
137
|
+
height: 100
|
|
138
|
+
},
|
|
139
|
+
listsPrefixesRenderers,
|
|
140
|
+
systemFonts,
|
|
141
|
+
fallbackFonts,
|
|
142
|
+
nestLevel: 0,
|
|
143
|
+
colorScheme: resolvedScheme,
|
|
144
|
+
darkModeStyles: darkModeStyles ?? {},
|
|
145
|
+
allowFontScaling,
|
|
146
|
+
maxFontSizeMultiplier
|
|
147
|
+
}), [contentWidth, effectiveTagsStyles, classesStyles, idsStyles, customRenderers, onLinkPress, onImagePress, renderersProps, emSize, debug, ignoredTagsSet, ignoredStylesSet, allowedStylesSet, defaultTextProps, defaultViewProps, maxImagesWidth, imagesInitialDimensions, listsPrefixesRenderers, systemFonts, fallbackFonts, resolvedScheme, darkModeStyles, allowFontScaling, maxFontSizeMultiplier]);
|
|
148
|
+
|
|
149
|
+
// --- Debug log ---
|
|
150
|
+
if (debug) {
|
|
151
|
+
console.log('[HtmlRenderer] Parsed DOM:', JSON.stringify(nodes, null, 2));
|
|
152
|
+
console.log('[HtmlRenderer] Color scheme:', resolvedScheme);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// --- Render ---
|
|
156
|
+
const rendered = useMemo(() => {
|
|
157
|
+
try {
|
|
158
|
+
return renderNodes(nodes, ctx, 'rn');
|
|
159
|
+
} catch (e) {
|
|
160
|
+
const error = e instanceof Error ? e : new Error('Failed to render HTML');
|
|
161
|
+
if (debug) {
|
|
162
|
+
console.error('[HtmlRenderer] Render error:', error);
|
|
163
|
+
}
|
|
164
|
+
onError?.(error);
|
|
165
|
+
return [];
|
|
166
|
+
}
|
|
167
|
+
}, [nodes, ctx, debug, onError]);
|
|
168
|
+
return /*#__PURE__*/_jsx(ErrorBoundary, {
|
|
169
|
+
onError: onError,
|
|
170
|
+
fallback: fallback,
|
|
171
|
+
children: /*#__PURE__*/_jsx(HtmlRendererContext.Provider, {
|
|
172
|
+
value: ctx,
|
|
173
|
+
children: /*#__PURE__*/_jsx(View, {
|
|
174
|
+
style: [containerStyle, baseStyle],
|
|
175
|
+
children: rendered
|
|
176
|
+
})
|
|
177
|
+
})
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
const containerStyle = {
|
|
181
|
+
flexShrink: 1
|
|
182
|
+
};
|
|
183
|
+
//# sourceMappingURL=HtmlRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useMemo","View","useColorScheme","HtmlRendererContext","parseHTML","getDefaultDarkModeStyles","renderNodes","ErrorBoundary","sanitizeDOM","getCachedDOM","setCachedDOM","buildDOMCacheKey","jsx","_jsx","HtmlRenderer","html","contentWidth","baseStyle","tagsStyles","classesStyles","idsStyles","customRenderers","onLinkPress","onImagePress","onError","fallback","ignoredTags","ignoredStyles","allowedStyles","defaultTextProps","defaultViewProps","renderersProps","maxImagesWidth","imagesInitialDimensions","listsPrefixesRenderers","emSize","systemFonts","fallbackFonts","debug","allowDangerousHtml","darkModeStyles","colorScheme","colorSchemeProp","allowFontScaling","maxFontSizeMultiplier","systemScheme","resolvedScheme","isDark","ignoredTagsSet","Set","ignoredStylesSet","allowedStylesSet","nodes","cacheKey","cached","parsed","e","error","Error","console","effectiveTagsStyles","base","defaultDark","userDark","merged","tag","Object","keys","ctx","width","height","nestLevel","log","JSON","stringify","rendered","children","Provider","value","style","containerStyle","flexShrink"],"sourceRoot":"../../src","sources":["HtmlRenderer.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { createContext, useContext } from 'react';
|
|
4
|
+
const DEFAULT_CONTEXT = {
|
|
5
|
+
contentWidth: 300,
|
|
6
|
+
tagsStyles: {},
|
|
7
|
+
classesStyles: {},
|
|
8
|
+
idsStyles: {},
|
|
9
|
+
customRenderers: {},
|
|
10
|
+
renderersProps: {},
|
|
11
|
+
emSize: 14,
|
|
12
|
+
debug: false,
|
|
13
|
+
ignoredTags: new Set(),
|
|
14
|
+
ignoredStyles: new Set(),
|
|
15
|
+
allowedStyles: null,
|
|
16
|
+
imagesInitialDimensions: {
|
|
17
|
+
width: 100,
|
|
18
|
+
height: 100
|
|
19
|
+
},
|
|
20
|
+
nestLevel: 0,
|
|
21
|
+
colorScheme: 'light',
|
|
22
|
+
darkModeStyles: {},
|
|
23
|
+
allowFontScaling: true,
|
|
24
|
+
maxFontSizeMultiplier: undefined
|
|
25
|
+
};
|
|
26
|
+
export const HtmlRendererContext = /*#__PURE__*/createContext(DEFAULT_CONTEXT);
|
|
27
|
+
|
|
28
|
+
/** Access the HtmlRenderer context from inside the render tree. */
|
|
29
|
+
export function useHtmlRendererContext() {
|
|
30
|
+
return useContext(HtmlRendererContext);
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["createContext","useContext","DEFAULT_CONTEXT","contentWidth","tagsStyles","classesStyles","idsStyles","customRenderers","renderersProps","emSize","debug","ignoredTags","Set","ignoredStyles","allowedStyles","imagesInitialDimensions","width","height","nestLevel","colorScheme","darkModeStyles","allowFontScaling","maxFontSizeMultiplier","undefined","HtmlRendererContext","useHtmlRendererContext"],"sourceRoot":"../../../src","sources":["context/index.tsx"],"mappings":";;AAAA,SAASA,aAAa,EAAEC,UAAU,QAAQ,OAAO;AAGjD,MAAMC,eAAyC,GAAG;EAChDC,YAAY,EAAE,GAAG;EACjBC,UAAU,EAAE,CAAC,CAAC;EACdC,aAAa,EAAE,CAAC,CAAC;EACjBC,SAAS,EAAE,CAAC,CAAC;EACbC,eAAe,EAAE,CAAC,CAAC;EACnBC,cAAc,EAAE,CAAC,CAAC;EAClBC,MAAM,EAAE,EAAE;EACVC,KAAK,EAAE,KAAK;EACZC,WAAW,EAAE,IAAIC,GAAG,CAAC,CAAC;EACtBC,aAAa,EAAE,IAAID,GAAG,CAAC,CAAC;EACxBE,aAAa,EAAE,IAAI;EACnBC,uBAAuB,EAAE;IAAEC,KAAK,EAAE,GAAG;IAAEC,MAAM,EAAE;EAAI,CAAC;EACpDC,SAAS,EAAE,CAAC;EACZC,WAAW,EAAE,OAAO;EACpBC,cAAc,EAAE,CAAC,CAAC;EAClBC,gBAAgB,EAAE,IAAI;EACtBC,qBAAqB,EAAEC;AACzB,CAAC;AAED,OAAO,MAAMC,mBAAmB,gBAC9BxB,aAAa,CAA2BE,eAAe,CAAC;;AAE1D;AACA,OAAO,SAASuB,sBAAsBA,CAAA,EAA6B;EACjE,OAAOxB,UAAU,CAACuB,mBAAmB,CAAC;AACxC","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useHtmlParser","useContentWidth","useTagStyle"],"sourceRoot":"../../../src","sources":["hooks/index.ts"],"mappings":";;AAAA,SAASA,aAAa,QAAQ,oBAAiB;AAC/C,SAASC,eAAe,QAAQ,sBAAmB;AACnD,SAASC,WAAW,QAAQ,kBAAe","ignoreList":[]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { useHtmlRendererContext } from "../context/index.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns the current `contentWidth` from the HtmlRenderer context.
|
|
7
|
+
* Useful inside custom renderers that need to know the available layout width.
|
|
8
|
+
*/
|
|
9
|
+
export function useContentWidth() {
|
|
10
|
+
return useHtmlRendererContext().contentWidth;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=useContentWidth.js.map
|