Skip to content

Commit 124c474

Browse files
committed
update
1 parent ad9aefa commit 124c474

File tree

4 files changed

+155
-114
lines changed

4 files changed

+155
-114
lines changed

src/Playground.res

Lines changed: 80 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,27 +1183,10 @@ module ControlPanel = {
11831183
url
11841184
}
11851185

1186-
let compiledCode = switch state {
1187-
| Ready(ready) =>
1188-
switch ready.result {
1189-
| Comp(Success(_)) => codeFromResult(ready.result)->Some
1190-
| _ => None
1191-
}
1192-
| _ => None
1193-
}
1194-
1195-
let onRunOutputClick = evt => {
1196-
ReactEvent.Mouse.preventDefault(evt)
1197-
RenderOutputManager.renderOutput(compiledCode)
1198-
}
1199-
12001186
<>
12011187
<div className="mr-2">
12021188
<Button onClick=onFormatClick> {React.string("Format")} </Button>
12031189
</div>
1204-
<div className="mr-2">
1205-
<Button onClick={onRunOutputClick}> {React.string("Run")} </Button>
1206-
</div>
12071190
<ShareButton actionIndicatorKey createShareLink />
12081191
</>
12091192
| _ => React.null
@@ -1225,6 +1208,67 @@ let locMsgToCmError = (~kind: CodeMirror.Error.kind, locMsg: Api.LocMsg.t): Code
12251208
}
12261209
}
12271210

1211+
module RenderOutput = {
1212+
@react.component
1213+
let make = (~compilerState: CompilerManagerHook.state) => {
1214+
let code = switch compilerState {
1215+
| Ready(ready) =>
1216+
switch ready.result {
1217+
| Comp(Success(_)) => ControlPanel.codeFromResult(ready.result)->Some
1218+
| _ => None
1219+
}
1220+
| _ => None
1221+
}
1222+
1223+
let valid = switch code {
1224+
| Some(code) =>
1225+
switch RenderOutputManager.renderOutput(code) {
1226+
| Ok(_) => true
1227+
| Error(_) => false
1228+
}
1229+
| None => false
1230+
}
1231+
1232+
let a =
1233+
<div className={""}>
1234+
<iframe
1235+
width="100%"
1236+
id="iframe-eval"
1237+
className="relative w-full text-gray-20"
1238+
srcDoc=RenderOutputManager.Frame.srcdoc
1239+
/>
1240+
</div>
1241+
1242+
a
1243+
1244+
// switch code {
1245+
// | Some(code) =>
1246+
// switch RenderOutputManager.renderOutput(code) {
1247+
// | Ok() =>
1248+
// <iframe
1249+
// width="100%"
1250+
// id="iframe-eval"
1251+
// className="relative w-full text-gray-20"
1252+
// srcDoc=RenderOutputManager.Frame.srcdoc
1253+
// />
1254+
// | Error() =>
1255+
// let code = `module App = {
1256+
// @react.component
1257+
// let make = () => {
1258+
// <ModuleName />
1259+
// }
1260+
// }`
1261+
// <div className={"whitespace-pre-wrap p-4 block"}>
1262+
// <p className={"mb-2"}> {React.string("To render element create a module App")} </p>
1263+
// <pre> {HighlightJs.renderHLJS(~code, ~darkmode=true, ~lang="rescript", ())} </pre>
1264+
// </div>
1265+
// }
1266+
1267+
// | _ => React.null
1268+
// }
1269+
}
1270+
}
1271+
12281272
module OutputPanel = {
12291273
@react.component
12301274
let make = (
@@ -1253,13 +1297,13 @@ module OutputPanel = {
12531297
if type_ === "log" {
12541298
let args: array<string> = data["args"]
12551299

1256-
setLogs(
1257-
previousLogs =>
1258-
previousLogs
1259-
->Belt.Option.getWithDefault([])
1260-
->Js.Array2.concat([args])
1261-
->Some,
1262-
)
1300+
// setLogs(
1301+
// previousLogs =>
1302+
// logs
1303+
// ->Belt.Option.getWithDefault([])
1304+
// ->Js.Array2.concat([args])
1305+
// ->Some,
1306+
// )
12631307
}
12641308
})
12651309
None
@@ -1316,22 +1360,6 @@ module OutputPanel = {
13161360
{HighlightJs.renderHLJS(~code, ~darkmode=true, ~lang="js", ())}
13171361
</pre>
13181362

1319-
let renderOutputPane: React.element = switch compilerState {
1320-
| Compiling(ready, _)
1321-
| Ready(ready) =>
1322-
switch ready.result {
1323-
| Comp(Success(_)) =>
1324-
<iframe
1325-
width="100%"
1326-
id="iframe-eval"
1327-
className="relative w-full text-gray-20"
1328-
srcDoc=RenderOutputManager.Frame.srcdoc
1329-
/>
1330-
| _ => React.null
1331-
}
1332-
| _ => React.null
1333-
}
1334-
13351363
let consolePanel = switch logs {
13361364
| Some(logs) =>
13371365
let content =
@@ -1397,7 +1425,7 @@ module OutputPanel = {
13971425
prevSelected.current = selected
13981426

13991427
let tabs = [
1400-
(RenderOutput, renderOutputPane),
1428+
(RenderOutput, <RenderOutput compilerState />),
14011429
(Console, consolePanel),
14021430
(JavaScript, output),
14031431
(Problems, errorPane),
@@ -1445,60 +1473,30 @@ module App = {
14451473
}
14461474
`
14471475

1448-
let since_10_1 = `@@jsxConfig({ version: 4, mode: "classic" })
1476+
let since_10_1 = `@@jsxConfig({version: 4, mode: "classic"})
14491477
1450-
module CounterMessage = {
1478+
module Button = {
14511479
@react.component
1452-
let make = (~count, ~username=?) => {
1480+
let make = () => {
1481+
let (count, setCount) = React.useState(_ => 0)
14531482
let times = switch count {
14541483
| 1 => "once"
14551484
| 2 => "twice"
1456-
| n => Belt.Int.toString(n) ++ " times"
1457-
}
1458-
1459-
let name = switch username {
1460-
| Some("") => "Anonymous"
1461-
| Some(name) => name
1462-
| None => "Anonymous"
1485+
| n => n->Int.toString ++ " times"
14631486
}
1487+
let msg = \`Click me $\{times\}\`
14641488
1465-
<div> {React.string(\`Hello \$\{name\}, you clicked me \` ++ times)} </div>
1489+
<button onClick={_ => setCount(c => c + 1)}> {msg->React.string} </button>
14661490
}
14671491
}
14681492
1469-
module Form = {
1493+
module App = {
14701494
@react.component
14711495
let make = () => {
1472-
let (count, setCount) = React.useState(() => 0)
1473-
let (username, setUsername) = React.useState(() => "Anonymous")
1474-
1475-
<div>
1476-
{React.string("Username: ")}
1477-
<input
1478-
type_="text"
1479-
value={username}
1480-
onChange={evt => {
1481-
evt->ReactEvent.Form.preventDefault
1482-
let username = (evt->ReactEvent.Form.target)["value"]
1483-
setUsername(_prev => username)
1484-
}}
1485-
/>
1486-
<button
1487-
onClick={_evt => {
1488-
setCount(prev => prev + 1)
1489-
}}>
1490-
{React.string("Click me")}
1491-
</button>
1492-
<button onClick={_evt => setCount(_ => 0)}> {React.string("Reset")} </button>
1493-
<CounterMessage count username />
1494-
</div>
1496+
<Button />
14951497
}
14961498
}
14971499
1498-
module App = {
1499-
@react.component
1500-
let make = () => <Form/>
1501-
}
15021500
`
15031501
}
15041502

@@ -1783,7 +1781,7 @@ let make = (~versions: array<string>) => {
17831781
| _ => "rescript"
17841782
}
17851783

1786-
let (currentTab, setCurrentTab) = React.useState(_ => RenderOutput)
1784+
let (currentTab, setCurrentTab) = React.useState(_ => JavaScript)
17871785

17881786
let disabled = false
17891787

@@ -1793,7 +1791,7 @@ let make = (~versions: array<string>) => {
17931791
"flex-1 items-center p-4 border-t-4 border-transparent " ++ activeClass
17941792
}
17951793

1796-
let tabs = [RenderOutput, Console, JavaScript, Problems, Settings]
1794+
let tabs = [JavaScript, RenderOutput, Console, Problems, Settings]
17971795

17981796
let headers = Belt.Array.mapWithIndex(tabs, (i, tab) => {
17991797
let title = switch tab {

src/bindings/Webapi.res

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
module Document = {
2+
@val external document: Dom.element = "document"
23
@scope("document") @val external createElement: string => Dom.element = "createElement"
34
@scope("document") @val external createTextNode: string => Dom.element = "createTextNode"
45
}
@@ -15,6 +16,14 @@ module Element = {
1516
@get external classList: Dom.element => ClassList.t = "classList"
1617
@send external getBoundingClientRect: Dom.element => {..} = "getBoundingClientRect"
1718

19+
@send
20+
external getElementById: (Dom.element, string) => Js.nullable<Dom.element> = "getElementById"
21+
22+
type contentWindow
23+
@get external contentWindow: Dom.element => option<contentWindow> = "contentWindow"
24+
25+
@send external postMessage: (contentWindow, string, string) => unit = "postMessage"
26+
1827
module Style = {
1928
@scope("style") @set external width: (Dom.element, string) => unit = "width"
2029
@scope("style") @set external height: (Dom.element, string) => unit = "height"

src/common/RenderOutputManager.res

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,35 @@
1-
module Transpiler = {
2-
@module("../ffi/removeImportsAndExports") external transpile: string => string = "default"
1+
module AcornParse = {
2+
type t
3+
@module("../ffi/acorn-parse.js") external parse: string => t = "parse"
4+
5+
@module("../ffi/acorn-parse.js") external hasEntryPoint: t => bool = "hasEntryPoint"
6+
7+
@module("../ffi/acorn-parse.js")
8+
external removeImportsAndExports: t => string = "removeImportsAndExports"
9+
}
310

11+
module Transpiler = {
412
let run = code =>
513
`(function () {
6-
${transpile(code)}
14+
${code}
715
const root = document.getElementById("root");
816
ReactDOM.render(App.make(), root);
917
})();`
1018
}
1119

1220
module Frame = {
13-
type document
14-
type element
15-
type contentWindow
16-
@send external postMessage: (contentWindow, string, string) => unit = "postMessage"
17-
@get external contentWindow: element => option<contentWindow> = "contentWindow"
18-
@send external getElementById: (document, string) => Js.nullable<element> = "getElementById"
19-
@val external doc: document = "document"
21+
let css = `body {
22+
background-color: inherit;
23+
color: CanvasText;
24+
color-scheme: light dark;
25+
}`
2026

2127
let srcdoc = `
2228
<html>
2329
<head>
2430
<meta charset="UTF-8" />
2531
<title>Playground Output</title>
26-
<style>
27-
* {
28-
color: rgb(205, 205, 214);
29-
}
30-
</style>
32+
<style>${css}</style>
3133
</head>
3234
<body>
3335
<div id="root"></div>
@@ -39,10 +41,6 @@ module Frame = {
3941
src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"
4042
crossorigin
4143
></script>
42-
<script
43-
src="https://bundleplayground.s3.sa-east-1.amazonaws.com/bundle.js"
44-
crossorigin
45-
></script>
4644
<script>
4745
window.addEventListener("message", (event) => {
4846
try {
@@ -66,20 +64,31 @@ module Frame = {
6664
`
6765

6866
let sendOutput = code => {
69-
let frame = Js.toOption(doc->getElementById("iframe-eval"))
67+
open Webapi
68+
69+
let frame =
70+
Document.document
71+
->Element.getElementById("iframe-eval")
72+
->Js.Nullable.toOption
73+
7074
switch frame {
7175
| Some(element) =>
72-
switch element->contentWindow {
73-
| Some(win) => win->postMessage(code, "*")
76+
switch element->Element.contentWindow {
77+
| Some(win) => win->Element.postMessage(code, "*")
7478
| None => ()
7579
}
7680
| None => ()
7781
}
7882
}
7983
}
8084

81-
let renderOutput = code =>
82-
switch code {
83-
| Some(code) => Transpiler.run(code)->Frame.sendOutput
84-
| None => ()
85+
let renderOutput = code => {
86+
let ast = AcornParse.parse(code)
87+
let transpiled = AcornParse.removeImportsAndExports(ast)
88+
switch AcornParse.hasEntryPoint(ast) {
89+
| true =>
90+
Transpiler.run(transpiled)->Frame.sendOutput
91+
Ok()
92+
| false => Error()
8593
}
94+
}

0 commit comments

Comments
 (0)