@@ -3,13 +3,15 @@ import type {TBabel, TReact, IStringToReactApi} from './types.d';
33import { FC } from 'react' ;
44class Ctx implements IStringToReactApi {
55 _temp : string = '' ;
6- _parentTemp : string = `"use strict";\nreturn @temp;` ;
6+ _blob : Blob | undefined = undefined ;
7+ _rerender : ( state : { } ) => void = ( ) => { } ;
78 _com : FC = function ( ) {
89 return null ;
910 } ;
1011 _getBabel : ( ) => TBabel ;
1112 _getReact : ( ) => TReact ;
12- constructor ( React : TReact , Babel : TBabel ) {
13+ constructor ( React : TReact , Babel : TBabel , rerender : ( state : { } ) => void ) {
14+ this . _rerender = rerender ;
1315 this . _getReact = ( ) => React ;
1416 if ( ! Babel ) {
1517 throw new Error (
@@ -22,6 +24,9 @@ class Ctx implements IStringToReactApi {
2224 if ( Object . prototype . toString . call ( babelOptions ) !== '[object Object]' ) {
2325 throw new Error ( `babelOptions prop of string-to-react-component element should be an object.` ) ;
2426 }
27+ if ( Object . prototype . hasOwnProperty . call ( babelOptions , 'sourceMaps' ) === false ) {
28+ babelOptions . sourceMaps = 'inline' ;
29+ }
2530 if ( Object . prototype . hasOwnProperty . call ( babelOptions , 'presets' ) === false ) {
2631 babelOptions . presets = [ 'react' ] ;
2732 } else {
@@ -34,49 +39,44 @@ class Ctx implements IStringToReactApi {
3439 }
3540 }
3641 }
37- getModule ( code : string , babelOptions : TransformOptions ) : Promise < any > {
38- this . _checkBabelOptions ( babelOptions ) ;
39- code = `import React from "react";\nexport default ${ code } ` ;
40- const resultObj = this . _getBabel ( ) . transform ( code , babelOptions ) ;
41- // 1. Define your module code as a string
42- code = resultObj . code || '' ;
43- code = code
42+ _prependCode ( template : string ) : IStringToReactApi {
43+ this . _temp = `import React from "react";\nexport default ${ template } ` ;
44+ return this ;
45+ }
46+ _postpendCode ( ) : string {
47+ return this . _temp
4448 . replace ( 'export default' , 'export default (React)=>' )
4549 . replace ( 'import React from "react";' , '//import React from "react";' ) ;
46-
47- // 2. Create a Blob containing the module code
48- const blob = new Blob ( [ code ] , { type : 'application/javascript' } ) ;
49- // 3. Create a URL for the Blob
50+ }
51+ _getBlob ( temp : string ) : Blob {
52+ return new Blob ( [ temp ] , { type : 'application/javascript' } ) ;
53+ }
54+ _getModule ( blob : Blob ) : Promise < FC > {
5055 const moduleUrl = URL . createObjectURL ( blob ) ;
51- // 4. Dynamically import the module using import()
5256 return import ( /* webpackIgnore: true */ moduleUrl )
5357 . then ( ( module ) => {
54- // Clean up by revoking the object URL
5558 URL . revokeObjectURL ( moduleUrl ) ;
56-
5759 return Promise . resolve ( ( module ?. default || module ) ( this . _getReact ( ) ) ) ;
5860 } )
5961 . catch ( ( error ) => {
60- console . error ( 'Error loading module:' , error ) ;
62+ URL . revokeObjectURL ( moduleUrl ) ;
63+ const errorTitle : string = 'string-to-react-component loading module is failed:' ;
64+ console . error ( errorTitle , error ) ;
65+ throw new Error ( errorTitle ) ;
6166 } ) ;
6267 }
63- _transpile ( babelOptions : TransformOptions ) : string {
64- // make sure react presets is registered in babelOptions
68+ _transpile ( babelOptions : TransformOptions ) : IStringToReactApi {
6569 this . _checkBabelOptions ( babelOptions ) ;
6670 const resultObj = this . _getBabel ( ) . transform ( this . _temp , babelOptions ) ;
67- const filename = babelOptions . filename ;
6871 let code = resultObj . code ;
69- if ( filename ) {
70- code = resultObj . code + `\n//# sourceURL=${ filename } ` ;
71- }
72- return code || 'null' ;
73- }
74- _generateCom ( babelOptions : any ) {
75- this . _com = Function ( this . _parentTemp . replace ( '@temp' , this . _transpile ( babelOptions ) ) ) ( ) ;
76- this . _validateCodeInsideTheTemp ( ) ;
72+ // if (babelOptions.filename) {
73+ // code = resultObj.code + `\n//# sourceURL=${babelOptions.filename}`;
74+ // }
75+ this . _temp = code || 'null' ;
76+ return this ;
7777 }
78- _validateCodeInsideTheTemp ( ) {
79- if ( typeof this . _com !== 'function' ) {
78+ _validateCodeInsideTheTemp ( com : any ) : void {
79+ if ( typeof com !== 'function' ) {
8080 throw new Error ( `code inside the passed string into string-to-react-component, should be a function` ) ;
8181 }
8282 }
@@ -88,13 +88,26 @@ class Ctx implements IStringToReactApi {
8888 throw new Error ( `passed string into string-to-react-component element can not be empty` ) ;
8989 }
9090 }
91- updateTemplate ( template : string , babelOptions : TransformOptions ) : IStringToReactApi {
92- this . _validateTemplate ( template ) ;
91+ /** update transpiled code */
92+ _updateTemplate ( template : string , babelOptions : TransformOptions ) : string {
9393 if ( template !== this . _temp ) {
94- this . _temp = template ;
95- this . _generateCom ( babelOptions ) ;
94+ this . _validateTemplate ( template ) ;
95+ return this . _prependCode ( template ) . _transpile ( babelOptions ) . _postpendCode ( ) ;
9696 }
97- return this ;
97+ return this . _temp ;
98+ }
99+ update ( template : string , babelOptions : TransformOptions ) : void {
100+ this . _updateComponent ( this . _updateTemplate ( template , babelOptions ) , babelOptions ) ;
101+ }
102+ _onChangeComponent ( ) : void {
103+ this . _rerender ( { } ) ;
104+ }
105+ _updateComponent ( template : string , babelOptions : TransformOptions ) : void {
106+ this . _getModule ( this . _getBlob ( template ) ) . then ( ( com : FC ) => {
107+ this . _validateCodeInsideTheTemp ( com ) ;
108+ this . _com = com ;
109+ this . _onChangeComponent ( ) ;
110+ } ) ;
98111 }
99112 getComponent ( ) : FC {
100113 return this . _com ;
0 commit comments