@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
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import type { DOMNode, DOMElement } from '../types';
|
|
2
|
+
|
|
3
|
+
/** Tags considered dangerous and stripped when `allowDangerousHtml` is false. */
|
|
4
|
+
const DANGEROUS_TAGS = new Set([
|
|
5
|
+
'script',
|
|
6
|
+
'iframe',
|
|
7
|
+
'object',
|
|
8
|
+
'embed',
|
|
9
|
+
'form',
|
|
10
|
+
'applet',
|
|
11
|
+
'base',
|
|
12
|
+
'svg',
|
|
13
|
+
'math',
|
|
14
|
+
'frame',
|
|
15
|
+
'frameset',
|
|
16
|
+
'template',
|
|
17
|
+
'noscript',
|
|
18
|
+
]);
|
|
19
|
+
|
|
20
|
+
/** Attributes that carry URLs and must be checked for dangerous schemes. */
|
|
21
|
+
const URL_ATTRIBUTES = new Set([
|
|
22
|
+
'href',
|
|
23
|
+
'src',
|
|
24
|
+
'srcset',
|
|
25
|
+
'poster',
|
|
26
|
+
'action',
|
|
27
|
+
'formaction',
|
|
28
|
+
'data',
|
|
29
|
+
'background',
|
|
30
|
+
'xlink:href',
|
|
31
|
+
'srcdoc',
|
|
32
|
+
]);
|
|
33
|
+
|
|
34
|
+
/** Attribute keys that should never be copied to the output. */
|
|
35
|
+
const BLOCKED_ATTR_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
36
|
+
|
|
37
|
+
/** Allowed URL schemes for links and resources. Everything else is blocked. */
|
|
38
|
+
const SAFE_SCHEMES = new Set([
|
|
39
|
+
'http:',
|
|
40
|
+
'https:',
|
|
41
|
+
'mailto:',
|
|
42
|
+
'tel:',
|
|
43
|
+
'sms:',
|
|
44
|
+
'geo:',
|
|
45
|
+
'data:image/', // only data: images are safe
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
/** Max recursion depth for sanitizing nested DOM trees. */
|
|
49
|
+
const MAX_DEPTH = 100;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Strip ASCII control characters (0x00–0x1F), tabs, newlines, and carriage
|
|
53
|
+
* returns from a string before checking schemes. This prevents bypass via
|
|
54
|
+
* null-byte injection or embedded whitespace (e.g. `java\tscript:`).
|
|
55
|
+
*/
|
|
56
|
+
function normalizeUrl(url: string): string {
|
|
57
|
+
return url
|
|
58
|
+
.replace(/[\x00-\x1f\x7f]/g, '')
|
|
59
|
+
.trim()
|
|
60
|
+
.toLowerCase();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Returns true if the URL uses a safe, allowed scheme.
|
|
65
|
+
* Blocks `javascript:`, `vbscript:`, `data:text/*`, and any other unknown scheme.
|
|
66
|
+
*/
|
|
67
|
+
function isSafeUrl(url: string): boolean {
|
|
68
|
+
const normalized = normalizeUrl(url);
|
|
69
|
+
|
|
70
|
+
// Relative URLs and fragment-only URLs are safe
|
|
71
|
+
if (
|
|
72
|
+
normalized.startsWith('/') ||
|
|
73
|
+
normalized.startsWith('#') ||
|
|
74
|
+
normalized.startsWith('?') ||
|
|
75
|
+
!normalized.includes(':')
|
|
76
|
+
) {
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Check against allowed schemes
|
|
81
|
+
for (const scheme of SAFE_SCHEMES) {
|
|
82
|
+
if (normalized.startsWith(scheme)) return true;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Recursively sanitize a DOM tree:
|
|
90
|
+
* - Remove dangerous tags entirely (including children)
|
|
91
|
+
* - Strip ALL event handler attributes (any attribute starting with `on`)
|
|
92
|
+
* - Neutralize dangerous URLs in all URL-bearing attributes
|
|
93
|
+
* - Guard against prototype pollution via attribute keys
|
|
94
|
+
* - Enforce a max recursion depth to prevent stack overflow
|
|
95
|
+
*/
|
|
96
|
+
export function sanitizeDOM(nodes: DOMNode[], depth: number = 0): DOMNode[] {
|
|
97
|
+
if (depth > MAX_DEPTH) return [];
|
|
98
|
+
|
|
99
|
+
const result: DOMNode[] = [];
|
|
100
|
+
|
|
101
|
+
for (const node of nodes) {
|
|
102
|
+
if (node.type === 'text') {
|
|
103
|
+
result.push(node);
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Strip dangerous tags entirely (including children)
|
|
108
|
+
if (DANGEROUS_TAGS.has(node.tag)) {
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Clean attributes
|
|
113
|
+
const cleanAttrs = Object.create(null) as Record<string, string>;
|
|
114
|
+
|
|
115
|
+
for (const [key, value] of Object.entries(node.attributes)) {
|
|
116
|
+
const keyLower = key.toLowerCase();
|
|
117
|
+
|
|
118
|
+
// Strip event handlers (any attribute starting with "on")
|
|
119
|
+
if (keyLower.startsWith('on')) continue;
|
|
120
|
+
|
|
121
|
+
// Guard against prototype pollution
|
|
122
|
+
if (BLOCKED_ATTR_KEYS.has(keyLower)) continue;
|
|
123
|
+
|
|
124
|
+
// Sanitize URL-bearing attributes
|
|
125
|
+
if (URL_ATTRIBUTES.has(keyLower)) {
|
|
126
|
+
if (!isSafeUrl(value)) {
|
|
127
|
+
// For href, replace with #; for others, drop entirely
|
|
128
|
+
if (keyLower === 'href') {
|
|
129
|
+
cleanAttrs[key] = '#';
|
|
130
|
+
}
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
cleanAttrs[key] = value;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const sanitizedElement: DOMElement = {
|
|
139
|
+
type: 'element',
|
|
140
|
+
tag: node.tag,
|
|
141
|
+
attributes: cleanAttrs,
|
|
142
|
+
children: sanitizeDOM(node.children, depth + 1),
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
result.push(sanitizedElement);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return result;
|
|
149
|
+
}
|