11import * as Acorn from 'acorn'
22import * as AcornJSX from 'acorn-jsx'
3- import React , { ComponentType , ExoticComponent , Fragment } from 'react'
3+ import React , { Fragment } from 'react'
44import ATTRIBUTES from '../constants/attributeNames'
55import { canHaveChildren , canHaveWhitespace } from '../constants/specialTags'
66import { NullishShortCircuit } from '../errors/NullishShortCircuit'
@@ -14,24 +14,74 @@ function handleNaN<T>(child: T): T | 'NaN' {
1414
1515type ParsedJSX = React . ReactNode | boolean | string
1616type ParsedTree = ParsedJSX | ParsedJSX [ ] | null
17+
18+ /**
19+ * Props for the JsxParser component
20+ */
1721export type TProps = {
22+ /** Whether to allow rendering of unrecognized HTML elements. Defaults to true. */
1823 allowUnknownElements ?: boolean ,
24+
25+ /**
26+ * Whether to auto-close void elements like <img>, <br>, <hr> etc. in HTML style.
27+ * Defaults to false.
28+ */
1929 autoCloseVoidElements ?: boolean ,
30+
31+ /** Object containing values that can be referenced in the JSX string */
2032 bindings ?: { [ key : string ] : unknown ; } ,
33+
34+ /**
35+ * Array of attribute names or RegExp patterns to blacklist.
36+ * By default removes 'on*' attributes
37+ */
2138 blacklistedAttrs ?: Array < string | RegExp > ,
39+
40+ /**
41+ * Array of HTML tag names to blacklist.
42+ * By default removes 'script' tags
43+ */
2244 blacklistedTags ?: string [ ] ,
45+
46+ /** CSS class name(s) to add to the wrapper div */
2347 className ?: string ,
24- components ?: Record < string , ComponentType | ExoticComponent > ,
48+
49+ /** Map of component names to their React component definitions */
50+ components ?: Record <
51+ string ,
52+ | React . ComponentType // allows for class components
53+ | React . ExoticComponent // allows for forwardRef
54+ | ( ( ) => React . ReactNode ) // allows for function components
55+ > ,
56+
57+ /** If true, only renders custom components defined in the components prop */
2558 componentsOnly ?: boolean ,
59+
60+ /** If true, disables usage of React.Fragment. May affect whitespace handling */
2661 disableFragments ?: boolean ,
62+
63+ /** If true, disables automatic generation of key props */
2764 disableKeyGeneration ?: boolean ,
65+
66+ /** The JSX string to parse and render */
2867 jsx ?: string ,
68+
69+ /** Callback function when parsing/rendering errors occur */
2970 onError ?: ( error : Error ) => void ,
71+
72+ /** If true, shows parsing/rendering warnings in console */
3073 showWarnings ?: boolean ,
74+
75+ /** Custom error renderer function */
3176 renderError ?: ( props : { error : string } ) => React . ReactNode | null ,
77+
78+ /** Whether to wrap output in a div. If false, renders children directly */
3279 renderInWrapper ?: boolean ,
80+
81+ /** Custom renderer for unrecognized elements */
3382 renderUnrecognized ?: ( tagName : string ) => React . ReactNode | null ,
3483}
84+
3585type Scope = Record < string , any >
3686
3787export default class JsxParser extends React . Component < TProps > {
@@ -55,8 +105,14 @@ export default class JsxParser extends React.Component<TProps> {
55105 renderUnrecognized : ( ) => null ,
56106 }
57107
108+ /** Stores the parsed React elements */
58109 private ParsedChildren : ParsedTree = null
59110
111+ /**
112+ * Parses a JSX string into React elements
113+ * @param jsx - The JSX string to parse
114+ * @returns The parsed React node(s) or null if parsing fails
115+ */
60116 #parseJSX = ( jsx : string ) : React . ReactNode | React . ReactNode [ ] | null => {
61117 const parser = Acorn . Parser . extend ( AcornJSX . default ( {
62118 autoCloseVoidElements : this . props . autoCloseVoidElements ,
@@ -80,6 +136,12 @@ export default class JsxParser extends React.Component<TProps> {
80136 return parsed . map ( p => this . #parseExpression( p ) ) . filter ( Boolean )
81137 }
82138
139+ /**
140+ * Parses a single JSX expression into its corresponding value/element
141+ * @param expression - The JSX expression to parse
142+ * @param scope - Optional scope for variable resolution
143+ * @returns The parsed value/element
144+ */
83145 #parseExpression = ( expression : AcornJSX . Expression , scope ?: Scope ) : any => {
84146 switch ( expression . type ) {
85147 case 'JSXAttribute' :
@@ -204,6 +266,12 @@ export default class JsxParser extends React.Component<TProps> {
204266 }
205267 }
206268
269+ /**
270+ * Parses a chain expression (optional chaining)
271+ * @param expression - The chain expression to parse
272+ * @param scope - Optional scope for variable resolution
273+ * @returns The parsed value
274+ */
207275 #parseChainExpression = ( expression : AcornJSX . ChainExpression , scope ?: Scope ) : any => {
208276 try {
209277 return this . #parseExpression( expression . expression , scope )
@@ -213,6 +281,12 @@ export default class JsxParser extends React.Component<TProps> {
213281 }
214282 }
215283
284+ /**
285+ * Parses a member expression (e.g., obj.prop or obj['prop'])
286+ * @param expression - The member expression to parse
287+ * @param scope - Optional scope for variable resolution
288+ * @returns The resolved member value
289+ */
216290 #parseMemberExpression = ( expression : AcornJSX . MemberExpression , scope ?: Scope ) : any => {
217291 const object = this . #parseExpression( expression . object , scope )
218292
@@ -242,11 +316,22 @@ export default class JsxParser extends React.Component<TProps> {
242316 return member
243317 }
244318
319+ /**
320+ * Parses a JSX element name (simple or member expression)
321+ * @param element - The JSX identifier or member expression
322+ * @returns The parsed element name as a string
323+ */
245324 #parseName = ( element : AcornJSX . JSXIdentifier | AcornJSX . JSXMemberExpression ) : string => {
246325 if ( element . type === 'JSXIdentifier' ) { return element . name }
247326 return `${ this . #parseName( element . object ) } .${ this . #parseName( element . property ) } `
248327 }
249328
329+ /**
330+ * Parses a JSX element into React elements
331+ * @param element - The JSX element to parse
332+ * @param scope - Optional scope for variable resolution
333+ * @returns The parsed React node(s) or null
334+ */
250335 #parseElement = (
251336 element : AcornJSX . JSXElement | AcornJSX . JSXFragment ,
252337 scope ?: Scope ,
@@ -357,6 +442,10 @@ export default class JsxParser extends React.Component<TProps> {
357442 return React . createElement ( component || lowerName , props , children )
358443 }
359444
445+ /**
446+ * Renders the parsed JSX content
447+ * @returns The rendered React elements wrapped in a div (if renderInWrapper is true)
448+ */
360449 render ( ) {
361450 const jsx = ( this . props . jsx || '' ) . trim ( ) . replace ( / < ! D O C T Y P E ( [ ^ > ] * ) > / g, '' )
362451 this . ParsedChildren = this . #parseJSX( jsx )
0 commit comments