@@ -1548,8 +1548,8 @@ module AutomaticExpr = struct
15481548 | JSXPropValue (_ , _ , {pexp_loc} ) -> pexp_loc
15491549 | JSXPropSpreading (loc , _ ) -> loc
15501550
1551- let mk_record_from_props (jsx_expr_loc : Location.t ) ( props : jsx_props ) :
1552- expression =
1551+ let mk_record_from_props mapper (jsx_expr_loc : Location.t )
1552+ ( props : jsx_props ) : expression =
15531553 (* Create an artificial range from the first till the last prop *)
15541554 let loc =
15551555 match props with
@@ -1580,7 +1580,8 @@ module AutomaticExpr = struct
15801580 in
15811581 let props, spread_props =
15821582 match props with
1583- | JSXPropSpreading (_ , expr ) :: rest -> (rest, Some expr)
1583+ | JSXPropSpreading (_ , expr ) :: rest ->
1584+ (rest, Some (mapper.expr mapper expr))
15841585 | _ -> (props, None )
15851586 in
15861587
@@ -1592,7 +1593,9 @@ module AutomaticExpr = struct
15921593 Exp. ident {txt = Lident name.txt; loc = name.loc},
15931594 is_optional )
15941595 | JSXPropValue (name , is_optional , value ) ->
1595- ({txt = Lident name.txt; loc = name.loc}, value, is_optional)
1596+ ( {txt = Lident name.txt; loc = name.loc},
1597+ mapper.expr mapper value,
1598+ is_optional )
15961599 | JSXPropSpreading (loc , _ ) ->
15971600 (* There can only be one spread expression and it is expected to be the first prop *)
15981601 Jsx_common. raise_error ~loc
@@ -1694,7 +1697,7 @@ module AutomaticExpr = struct
16941697 {loc = Location. none; txt = Ldot (element_binding, " jsxKeyed" )},
16951698 [key_prop; (nolabel, unit_expr ~loc: Location. none)] )
16961699 in
1697- let props = mk_record_from_props loc props in
1700+ let props = mk_record_from_props mapper loc props in
16981701
16991702 Exp. apply ~loc ~attrs jsx_expr
17001703 ([(nolabel, component_name_expr); (nolabel, props)] @ key_and_unit)
@@ -1718,13 +1721,111 @@ module AutomaticExpr = struct
17181721 },
17191722 [key_prop; (nolabel, unit_expr ~loc: Location. none)] )
17201723 in
1721- let props = mk_record_from_props loc props in
1724+ let props = mk_record_from_props mapper loc props in
17221725 Exp. apply ~loc ~attrs jsx_expr
17231726 ([(nolabel, make_id); (nolabel, props)] @ key_and_unit)
17241727 else
17251728 Jsx_common. raise_error ~loc
17261729 " JSX: element name is neither upper- or lowercase, got \" %s\" "
17271730 (Longident. flatten tag_name.txt |> String. concat " ." )
1731+ | {
1732+ pexp_desc =
1733+ Pexp_jsx_container_element
1734+ {
1735+ jsx_container_element_tag_name_start = tag_name;
1736+ jsx_container_element_props = props;
1737+ jsx_container_element_children = children;
1738+ };
1739+ pexp_loc = loc;
1740+ pexp_attributes = attrs;
1741+ } ->
1742+ let loc = {loc with loc_ghost = true } in
1743+ let name = Longident. flatten tag_name.txt |> String. concat " ." in
1744+ (* For example: <div> <h1></h1> <br /> </div>
1745+ This has an impact if we want to use ReactDOM.jsx or ReactDOM.jsxs
1746+ *)
1747+ let has_multiple_literal_children =
1748+ match children with
1749+ | JSXChildrenItems (_ :: _ :: _ ) -> true
1750+ | _ -> false
1751+ in
1752+ if starts_with_lowercase name then
1753+ let component_name_expr = constant_string ~loc: tag_name.loc name in
1754+ let element_binding =
1755+ match config.module_ |> String. lowercase_ascii with
1756+ | "react" -> Lident " ReactDOM"
1757+ | _generic -> module_access_name config " Elements"
1758+ in
1759+ let props_record =
1760+ (* Append current props with JSXPropValue("children")
1761+ This will later be transformed correctly into a record. *)
1762+ let props_with_children =
1763+ match children with
1764+ | JSXChildrenItems [] -> props
1765+ | JSXChildrenItems [expr] | JSXChildrenSpreading expr ->
1766+ props
1767+ @ [
1768+ JSXPropValue
1769+ ( {txt = " children" ; loc = Location. none},
1770+ true ,
1771+ Exp. apply
1772+ (Exp. ident
1773+ {
1774+ txt = Ldot (element_binding, " someElement" );
1775+ loc = Location. none;
1776+ })
1777+ [(Nolabel , expr)] );
1778+ ]
1779+ | JSXChildrenItems xs ->
1780+ (* this is a hack to support react components that introspect into their children *)
1781+ props
1782+ @ [
1783+ JSXPropValue
1784+ ( {txt = " children" ; loc = Location. none},
1785+ false ,
1786+ Exp. apply
1787+ (Exp. ident
1788+ {
1789+ txt = module_access_name config " array" ;
1790+ loc = Location. none;
1791+ })
1792+ [
1793+ (Nolabel , Exp. array (List. map (mapper.expr mapper) xs));
1794+ ] );
1795+ ]
1796+ in
1797+ mk_record_from_props mapper loc props_with_children
1798+ in
1799+ let jsx_expr, key_and_unit =
1800+ match try_find_key_prop props with
1801+ | None ->
1802+ ( Exp. ident
1803+ {
1804+ loc = Location. none;
1805+ txt =
1806+ Ldot
1807+ ( element_binding,
1808+ if has_multiple_literal_children then " jsxs" else " jsx"
1809+ );
1810+ },
1811+ [] )
1812+ | Some key_prop ->
1813+ ( Exp. ident
1814+ {
1815+ loc = Location. none;
1816+ txt =
1817+ Ldot
1818+ ( element_binding,
1819+ if has_multiple_literal_children then " jsxsKeyed"
1820+ else " jsxKeyed" );
1821+ },
1822+ [key_prop; (nolabel, unit_expr ~loc: Location. none)] )
1823+ in
1824+
1825+ Exp. apply ~loc ~attrs jsx_expr
1826+ ([(nolabel, component_name_expr); (nolabel, props_record)]
1827+ @ key_and_unit)
1828+ else failwith " TODO"
17281829 | e -> default_mapper.expr mapper e
17291830end
17301831
0 commit comments