1
1
import * as vscode from "vscode" ;
2
2
3
- import * as crypto from "crypto" ;
4
- import { basename , join } from "path" ;
5
- import { tmpdir } from "os" ;
3
+ import * as path from "path" ;
4
+ import * as vm from "vm" ;
6
5
import * as esbuild from "esbuild" ;
7
6
8
7
import { render } from "@react-email/render" ;
9
- import { unlink } from "fs/promises" ;
10
-
11
- const extensionPreviewFolder = ".vscpreview" as const ;
12
8
13
9
export type BuiltEmail =
14
10
| {
15
- filename : string ;
16
- html : string ;
17
- text : string ;
18
- valid : true ;
19
- }
11
+ filename : string ;
12
+ html : string ;
13
+ text : string ;
14
+ valid : true ;
15
+ }
20
16
| { valid : false } ;
21
17
22
18
export async function renderOpenEmailFile (
@@ -32,51 +28,61 @@ export async function renderOpenEmailFile(
32
28
}
33
29
34
30
const currentlyOpenTabFilePath = activeEditor . document . fileName ; // actually a path not the name of the file
35
- const currentlyOpenTabFilename = basename ( currentlyOpenTabFilePath , ".tsx" ) ;
36
-
37
- // saves the temporary previews generated in the tmp folder
38
- const previewDirectory = join ( tmpdir ( ) , extensionPreviewFolder ) ;
39
-
40
- // this hash is needed so the the import doesn't get from its cache
41
- const renderingHash = crypto . randomBytes ( 20 ) . toString ( "hex" ) ;
42
-
43
- const builtFileWithCurrentContents = join (
44
- previewDirectory ,
45
- `${ currentlyOpenTabFilename } -${ renderingHash } .js` ,
31
+ const currentlyOpenTabFilename = path . basename (
32
+ currentlyOpenTabFilePath ,
33
+ ".tsx" ,
46
34
) ;
47
35
48
36
try {
49
- await esbuild . build ( {
37
+ const buildResult = await esbuild . build ( {
50
38
bundle : true ,
51
39
entryPoints : [ currentlyOpenTabFilePath ] ,
52
40
platform : "node" ,
53
- write : true ,
41
+ write : false ,
54
42
jsx : "automatic" ,
43
+ loader : {
44
+ // eslint-disable-next-line @typescript-eslint/naming-convention
45
+ ".js" : "jsx" ,
46
+ } ,
55
47
format : "cjs" ,
56
- outfile : builtFileWithCurrentContents ,
57
48
} ) ;
58
49
59
- // for future people debugging this: if this doesnt update the preview, might be because import keeps a cache
60
- // and the hash is not being unique (unlikely though)
61
- const email = require ( builtFileWithCurrentContents ) ;
50
+ console . log ( global ) ;
62
51
63
- if ( typeof email . default === "undefined" ) {
64
- await unlink ( builtFileWithCurrentContents ) ;
52
+ const fakeContext = {
53
+ ...global ,
54
+ process : {
55
+ env : { }
56
+ } ,
57
+ module : { exports : { default : undefined as unknown } } ,
58
+ __filanem : currentlyOpenTabFilePath ,
59
+ __dirname : path . dirname ( currentlyOpenTabFilePath ) ,
60
+ } ;
61
+
62
+ try {
63
+ vm . runInNewContext ( buildResult . outputFiles [ 0 ] . text , fakeContext , {
64
+ filename : currentlyOpenTabFilePath ,
65
+ } ) ;
66
+ } catch ( exception ) {
67
+ throw exception ;
68
+ }
65
69
66
- // this means there is no "export default ..." in the file
67
- return { valid : false } ;
70
+ if ( typeof fakeContext . module . exports . default !== "function" ) {
71
+ return {
72
+ valid : false ,
73
+ } ;
68
74
}
69
75
70
- const comp = email . default ( email . default . PreviewProps ?? { } ) ; // this may come without a defualt which might cause problems
76
+ const email = fakeContext . module . exports . default ;
77
+
78
+ const comp = email ( "PreviewProps" in email ? email . PreviewProps : { } ) ; // this may come without a defualt which might cause problems
71
79
const emailAsText = render ( comp , {
72
80
plainText : true ,
73
81
pretty : false ,
74
82
} ) ;
75
83
76
84
const emailAsHTML = render ( comp , { pretty : false } ) ;
77
85
78
- await unlink ( builtFileWithCurrentContents ) ;
79
-
80
86
return {
81
87
filename : currentlyOpenTabFilename ,
82
88
html : emailAsHTML ,
0 commit comments