Skip to content

Commit 6c88c4b

Browse files
committed
Update playground to accommodate newest 10.1 release. Also add version query param support
1 parent f4c71b1 commit 6c88c4b

File tree

3 files changed

+151
-8
lines changed

3 files changed

+151
-8
lines changed

src/Playground.res

+109-4
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,10 @@ module ControlPanel = {
12031203
| lang => [("ext", Api.Lang.toExt(lang))]
12041204
}
12051205

1206+
let version = ready.selected.compilerVersion
1207+
1208+
Js.Array2.push(params, ("version", "v" ++ version))->ignore
1209+
12061210
Js.Array2.push(
12071211
params,
12081212
("code", editorCode.current->LzString.compressToEncodedURIComponent),
@@ -1396,7 +1400,15 @@ module OutputPanel = {
13961400
}
13971401
}
13981402

1399-
let initialResContent = `module Button = {
1403+
/**
1404+
The initial content is somewhat based on the compiler version.
1405+
If we are handling a version that's beyond 10.1, we want to make
1406+
sure we are using an example that includes a JSX pragma to
1407+
inform the user that you are able to switch between jsx 3 / jsx 4
1408+
and the different jsx modes (classic and automatic).
1409+
*/
1410+
module InitialContent = {
1411+
let original = `module Button = {
14001412
@react.component
14011413
let make = (~count: int) => {
14021414
let times = switch count {
@@ -1409,7 +1421,61 @@ let initialResContent = `module Button = {
14091421
<button> {msg->React.string} </button>
14101422
}
14111423
}
1412-
` // Please note:
1424+
`
1425+
1426+
let since_10_1 = `@@jsxConfig({ version: 4, mode: "automatic" })
1427+
1428+
module CounterMessage = {
1429+
@react.component
1430+
let make = (~count, ~username=?) => {
1431+
let times = switch count {
1432+
| 1 => "once"
1433+
| 2 => "twice"
1434+
| n => Belt.Int.toString(n) ++ " times"
1435+
}
1436+
1437+
let name = switch username {
1438+
| Some("") => "Anonymous"
1439+
| Some(name) => name
1440+
| None => "Anonymous"
1441+
}
1442+
1443+
<div> {React.string(\`Hello \$\{name\}, you clicked me \` ++ times)} </div>
1444+
}
1445+
}
1446+
1447+
module App = {
1448+
@react.component
1449+
let make = () => {
1450+
let (count, setCount) = React.useState(() => 0)
1451+
let (username, setUsername) = React.useState(() => "Anonymous")
1452+
1453+
<div>
1454+
{React.string("Username: ")}
1455+
<input
1456+
type_="text"
1457+
value={username}
1458+
onChange={evt => {
1459+
evt->ReactEvent.Form.preventDefault
1460+
let username = (evt->ReactEvent.Form.target)["value"]
1461+
setUsername(_prev => username)
1462+
}}
1463+
/>
1464+
<button
1465+
onClick={_evt => {
1466+
setCount(prev => prev + 1)
1467+
}}>
1468+
{React.string("Click me")}
1469+
</button>
1470+
<button onClick={_evt => setCount(_ => 0)}> {React.string("Reset")} </button>
1471+
<CounterMessage count username />
1472+
</div>
1473+
}
1474+
}
1475+
`
1476+
}
1477+
1478+
// Please note:
14131479
// ---
14141480
// The Playground is still a work in progress
14151481
// ReScript / old Reason syntax should parse just
@@ -1420,10 +1486,31 @@ let initialResContent = `module Button = {
14201486

14211487
let initialReContent = j`Js.log("Hello Reason 3.6!");`
14221488

1489+
/**
1490+
Takes a `versionStr` starting with a "v" and ending in major.minor.patch (e.g.
1491+
"v10.1.0") returns major, minor, patch as an integer tuple if it's actually in
1492+
a x.y.z format, otherwise will return `None`.
1493+
*/
1494+
let parseVersion = (versionStr: string): option<(int, int, int)> => {
1495+
switch versionStr->Js.String2.replace("v", "")->Js.String2.split(".") {
1496+
| [major, minor, patch] =>
1497+
switch (major->Belt.Int.fromString, minor->Belt.Int.fromString, patch->Belt.Int.fromString) {
1498+
| (Some(major), Some(minor), Some(patch)) => Some((major, minor, patch))
1499+
| _ => None
1500+
}
1501+
| _ => None
1502+
}
1503+
}
1504+
14231505
@react.component
14241506
let default = () => {
14251507
let router = Next.Router.useRouter()
14261508

1509+
let initialVersion = switch Js.Dict.get(router.query, "version") {
1510+
| Some(version) => Some(version)
1511+
| None => CompilerManagerHook.CdnMeta.versions->Belt.Array.get(0)
1512+
}
1513+
14271514
let initialLang = switch Js.Dict.get(router.query, "ext") {
14281515
| Some("re") => Api.Lang.Reason
14291516
| _ => Api.Lang.Res
@@ -1433,14 +1520,32 @@ let default = () => {
14331520
| (Some(compressedCode), _) => LzString.decompressToEncodedURIComponent(compressedCode)
14341521
| (None, Reason) => initialReContent
14351522
| (None, Res)
1436-
| (None, _) => initialResContent
1523+
| (None, _) =>
1524+
switch initialVersion {
1525+
| Some(initialVersion) =>
1526+
switch parseVersion(initialVersion) {
1527+
| Some((major, minor, _)) =>
1528+
if major >= 10 && minor >= 1 {
1529+
InitialContent.since_10_1
1530+
} else {
1531+
InitialContent.original
1532+
}
1533+
| None => InitialContent.original
1534+
}
1535+
| None => InitialContent.original
1536+
}
14371537
}
14381538

14391539
// We don't count to infinity. This value is only required to trigger
14401540
// rerenders for specific components (ActivityIndicator)
14411541
let (actionCount, setActionCount) = React.useState(_ => 0)
14421542
let onAction = _ => setActionCount(prev => prev > 1000000 ? 0 : prev + 1)
1443-
let (compilerState, compilerDispatch) = useCompilerManager(~initialLang, ~onAction, ())
1543+
let (compilerState, compilerDispatch) = useCompilerManager(
1544+
~initialVersion?,
1545+
~initialLang,
1546+
~onAction,
1547+
(),
1548+
)
14441549

14451550
let overlayState = React.useState(() => false)
14461551

src/common/CompilerManagerHook.res

+36-4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ module CdnMeta = {
3838
// Make sure versions exist on https://cdn.rescript-lang.org
3939
// [0] = latest
4040
let versions = [
41+
"v10.1.2",
4142
"v10.0.1",
4243
"v10.0.0",
4344
"v9.1.2",
@@ -184,7 +185,12 @@ type action =
184185
// transition happened, or not. We need that for a ActivityIndicator
185186
// component to give feedback to the user that an action happened (useful in
186187
// cases where the output didn't visually change)
187-
let useCompilerManager = (~initialLang: Lang.t=Res, ~onAction: option<action => unit>=?, ()) => {
188+
let useCompilerManager = (
189+
~initialVersion: option<string>=?,
190+
~initialLang: Lang.t=Res,
191+
~onAction: option<action => unit>=?,
192+
(),
193+
) => {
188194
let (state, setState) = React.useState(_ => Init)
189195

190196
// Dispatch method for the public interface
@@ -326,17 +332,43 @@ let useCompilerManager = (~initialLang: Lang.t=Res, ~onAction: option<action =>
326332
| versions =>
327333
let latest = versions[0]
328334

335+
// If the provided initialVersion is not available, fall back
336+
// to "latest"
337+
let initVersion = switch initialVersion {
338+
| Some(version) =>
339+
if (
340+
CdnMeta.versions->Js.Array2.some(v => {
341+
version == v
342+
})
343+
) {
344+
version
345+
} else {
346+
latest
347+
}
348+
| None => latest
349+
}
350+
329351
// Latest version is already running on @rescript/react
330352
let libraries = ["@rescript/react"]
331353

332-
switch await attachCompilerAndLibraries(~version=latest, ~libraries, ()) {
354+
switch await attachCompilerAndLibraries(~version=initVersion, ~libraries, ()) {
333355
| Ok() =>
334356
let instance = Compiler.make()
335357
let apiVersion = apiVersion->Version.fromString
336-
let config = instance->Compiler.getConfig
358+
359+
// Note: The compiler bundle currently defaults to
360+
// commonjs when initiating the compiler, but our playground
361+
// should default to ES6. So we override the config
362+
// and use the `setConfig` function to sync up the
363+
// internal compiler state with our playground state.
364+
let config = {
365+
...instance->Compiler.getConfig,
366+
module_system: "es6",
367+
}
368+
instance->Compiler.setConfig(config)
337369

338370
let selected = {
339-
id: latest,
371+
id: initVersion,
340372
apiVersion,
341373
compilerVersion: instance->Compiler.version,
342374
ocamlVersion: instance->Compiler.ocamlVersion,

src/common/CompilerManagerHook.resi

+6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ module FinalResult: {
88
| Nothing
99
}
1010

11+
module CdnMeta: {
12+
/** All available versions on the CDN */
13+
let versions: array<string>
14+
}
15+
1116
type selected = {
1217
id: string, // The id used for loading the compiler bundle (ideally should be the same as compilerVersion)
1318
apiVersion: Version.t, // The playground API version in use
@@ -41,6 +46,7 @@ type action =
4146
| UpdateConfig(Config.t)
4247

4348
let useCompilerManager: (
49+
~initialVersion: string=?,
4450
~initialLang: Lang.t=?,
4551
~onAction: action => unit=?,
4652
unit,

0 commit comments

Comments
 (0)