From ac34e4cb196f7492791f0024ce36e4567caceea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Tsnobiladz=C3=A9?= Date: Tue, 12 Nov 2024 13:07:17 +0100 Subject: [PATCH 1/5] remove useless interface file (Next.res is now pure bindings) --- src/bindings/Next.resi | 135 ----------------------------------------- 1 file changed, 135 deletions(-) delete mode 100644 src/bindings/Next.resi diff --git a/src/bindings/Next.resi b/src/bindings/Next.resi deleted file mode 100644 index 2af334399..000000000 --- a/src/bindings/Next.resi +++ /dev/null @@ -1,135 +0,0 @@ -module GetServerSideProps: { - module Req: { - type t - } - - module Res: { - type t - - let setHeader: (t, string, string) => unit - let write: (t, string) => unit - let end_: t => unit - } - - // See: https://github.com/zeit/next.js/blob/canary/packages/next/types/index.d.ts - type context<'props, 'params> = { - params: 'params, - query: Dict.t, - req: Req.t, - res: Res.t, - } - - type t<'props, 'params> = context<'props, 'params> => promise<{"props": 'props}> -} - -module GetStaticProps: { - // See: https://github.com/zeit/next.js/blob/canary/packages/next/types/index.d.ts - type context<'props, 'params> = { - params: 'params, - query: Dict.t, - req: Nullable.t<'props>, - } - - type t<'props, 'params> = context<'props, 'params> => promise<{"props": 'props}> - - type revalidate<'props, 'params> = context<'props, 'params> => promise<{ - "props": 'props, - "revalidate": Nullable.t, - }> -} - -module GetStaticPaths: { - // 'params: dynamic route params used in dynamic routing paths - // Example: pages/[id].js would result in a 'params = { id: string } - type path<'params> = {params: 'params} - - type return<'params> = { - paths: array>, - fallback: bool, - } - - type t<'params> = unit => promise> -} - -module Link: { - @react.component - let make: ( - ~href: string, - ~_as: string=?, - ~prefetch: bool=?, - ~replace: bool=?, - ~shallow: bool=?, - ~passHref: bool=?, - ~children: React.element, - ~className: string=?, - ~target: string=?, - ) => React.element -} - -module Router: { - /* - Make sure to only register events via a useEffect hook! - */ - module Events: { - type t - - let on: ( - t, - [ - | #routeChangeStart(string => unit) - | #routeChangeComplete(string => unit) - | #hashChangeComplete(string => unit) - ], - ) => unit - - let off: ( - t, - [ - | #routeChangeStart(string => unit) - | #routeChangeComplete(string => unit) - | #hashChangeComplete(string => unit) - ], - ) => unit - } - - type router = { - route: string, - asPath: string, - events: Events.t, - pathname: string, - query: Dict.t, - } - - type pathObj = { - pathname: string, - query: Dict.t, - } - - let push: (router, string) => unit - let pushObj: (router, pathObj) => unit - - let useRouter: unit => router - - let replace: (router, string) => unit - let replaceObj: (router, pathObj) => unit -} - -module Head: { - @react.component - let make: (~children: React.element) => React.element -} - -module Error: { - @react.component - let make: (~statusCode: int, ~children: React.element) => React.element -} - -module Dynamic: { - type options = {ssr?: bool, loading?: unit => React.element} - - @module("next/dynamic") - external dynamic: (unit => promise<'a>, options) => 'a = "default" - - @val - external import: string => promise<'a> = "import" -} From eee4fbda1f7da80d5438e69f46ccff6bcedd97c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Tsnobiladz=C3=A9?= Date: Tue, 12 Nov 2024 13:07:58 +0100 Subject: [PATCH 2/5] use history replaceState for shallow replace on create share link --- src/Playground.res | 5 ++--- src/bindings/Webapi.res | 7 +++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Playground.res b/src/Playground.res index 77fc39eef..21b9d0769 100644 --- a/src/Playground.res +++ b/src/Playground.res @@ -1134,7 +1134,6 @@ module ControlPanel = { } } - @val @scope(("window", "location")) external origin: string = "origin" @react.component let make = ( ~actionIndicatorKey: string, @@ -1173,8 +1172,8 @@ module ControlPanel = { let querystring = params->Array.map(((key, value)) => key ++ "=" ++ value)->Array.join("&") - let url = origin ++ router.route ++ "?" ++ querystring - Next.Router.replace(router, url) + let url = router.route ++ "?" ++ querystring + Webapi.Window.History.replaceState(null, ~url) url } diff --git a/src/bindings/Webapi.res b/src/bindings/Webapi.res index a3a053279..79f0a78ab 100644 --- a/src/bindings/Webapi.res +++ b/src/bindings/Webapi.res @@ -48,6 +48,13 @@ module Window = { @scope("window") @val external innerWidth: int = "innerWidth" @scope("window") @val external innerHeight: int = "innerHeight" @scope("window") @val external scrollY: int = "scrollY" + + module History = { + @scope(("window", "history")) @val + external pushState: (nullable<'a>, @as(json`""`) _, ~url: string=?) => unit = "pushState" + @scope(("window", "history")) @val + external replaceState: (nullable<'a>, @as(json`""`) _, ~url: string=?) => unit = "replaceState" + } } module Fetch = { From 915053eaa7abb20a33a4915325a230cfee7d144a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Tsnobiladz=C3=A9?= Date: Tue, 12 Nov 2024 13:37:19 +0100 Subject: [PATCH 3/5] update playground URL continuously --- src/Playground.res | 35 +++++------------------------ src/bindings/Webapi.res | 4 ++++ src/common/CompilerManagerHook.res | 19 ++++++++++++++-- src/common/CompilerManagerHook.resi | 2 ++ 4 files changed, 28 insertions(+), 32 deletions(-) diff --git a/src/Playground.res b/src/Playground.res index 21b9d0769..11be6d4ee 100644 --- a/src/Playground.res +++ b/src/Playground.res @@ -1102,7 +1102,7 @@ module ControlPanel = { | CopySuccess @react.component - let make = (~createShareLink: unit => string, ~actionIndicatorKey: string) => { + let make = (~actionIndicatorKey: string) => { let (state, setState) = React.useState(() => Init) React.useEffect(() => { @@ -1112,8 +1112,7 @@ module ControlPanel = { let onClick = evt => { ReactEvent.Mouse.preventDefault(evt) - let url = createShareLink() - let ret = copyToClipboard(url) + let ret = copyToClipboard(Webapi.Window.Location.href) if ret { setState(_ => CopySuccess) } @@ -1143,46 +1142,22 @@ module ControlPanel = { ~runOutput, ~toggleRunOutput, ) => { - let router = Next.Router.useRouter() - let children = switch state { | Init => React.string("Initializing...") | SwitchingCompiler(_ready, _version) => React.string("Switching Compiler...") - | Compiling(ready, _) - | Ready(ready) => + | Compiling(_, _) + | Ready(_) => let onFormatClick = evt => { ReactEvent.Mouse.preventDefault(evt) dispatch(Format(editorCode.current)) } - let createShareLink = () => { - let params = switch ready.targetLang { - | Res => [] - | lang => [("ext", Api.Lang.toExt(lang))] - } - - let version = ready.selected.compilerVersion - - Array.push(params, ("version", "v" ++ version))->ignore - - Array.push( - params, - ("code", editorCode.current->LzString.compressToEncodedURIComponent), - )->ignore - - let querystring = params->Array.map(((key, value)) => key ++ "=" ++ value)->Array.join("&") - - let url = router.route ++ "?" ++ querystring - Webapi.Window.History.replaceState(null, ~url) - url - } -
toggleRunOutput()}> {React.string("Auto-run")} - +
| _ => React.null } diff --git a/src/bindings/Webapi.res b/src/bindings/Webapi.res index 79f0a78ab..c25856ec2 100644 --- a/src/bindings/Webapi.res +++ b/src/bindings/Webapi.res @@ -55,6 +55,10 @@ module Window = { @scope(("window", "history")) @val external replaceState: (nullable<'a>, @as(json`""`) _, ~url: string=?) => unit = "replaceState" } + + module Location = { + @scope(("window", "location")) @val external href: string = "href" + } } module Fetch = { diff --git a/src/common/CompilerManagerHook.res b/src/common/CompilerManagerHook.res index bebf9634a..f096afa48 100644 --- a/src/common/CompilerManagerHook.res +++ b/src/common/CompilerManagerHook.res @@ -242,6 +242,18 @@ type action = | CompileCode(Lang.t, string) | UpdateConfig(Config.t) +let createUrl = (pathName, {code, selected: {compilerVersion}, targetLang}) => { + let params = switch targetLang { + | Res => [] + | lang => [("ext", RescriptCompilerApi.Lang.toExt(lang))] + } + Array.push(params, ("version", "v" ++ compilerVersion)) + Array.push(params, ("code", code->LzString.compressToEncodedURIComponent)) + let querystring = params->Array.map(((key, value)) => key ++ "=" ++ value)->Array.join("&") + let url = pathName ++ "?" ++ querystring + url +} + // ~initialLang: // The target language the compiler should be set to during // playground initialization. If the compiler doesn't support the language, it @@ -261,6 +273,7 @@ let useCompilerManager = ( (), ) => { let (state, setState) = React.useState(_ => Init) + let router = Next.Router.useRouter() // Dispatch method for the public interface let dispatch = (action: action): unit => { @@ -528,8 +541,10 @@ let useCompilerManager = ( } setState(_ => Ready({...ready, result: FinalResult.Comp(compResult)})) - | SetupFailed(_) - | Ready(_) => () + | SetupFailed(_) => () + | Ready(ready) => + let url = createUrl(router.route, ready) + Webapi.Window.History.replaceState(null, ~url) } } diff --git a/src/common/CompilerManagerHook.resi b/src/common/CompilerManagerHook.resi index ac29d6e4d..129f51375 100644 --- a/src/common/CompilerManagerHook.resi +++ b/src/common/CompilerManagerHook.resi @@ -64,3 +64,5 @@ let useCompilerManager: ( ~versions: array, unit, ) => (state, action => unit) + +let createUrl: (string, ready) => string From 6d4ed7f3e2081db171620adb484b30c574a53632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Tsnobiladz=C3=A9?= Date: Tue, 12 Nov 2024 14:03:30 +0100 Subject: [PATCH 4/5] track module system in playground url --- src/Playground.res | 3 +++ src/common/CompilerManagerHook.res | 12 +++++++----- src/common/CompilerManagerHook.resi | 1 + 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Playground.res b/src/Playground.res index 11be6d4ee..e14932207 100644 --- a/src/Playground.res +++ b/src/Playground.res @@ -1429,6 +1429,8 @@ let make = (~versions: array) => { | _ => Api.Lang.Res } + let initialModuleSystem = Dict.get(router.query, "module") + let initialContent = switch (Dict.get(router.query, "code"), initialLang) { | (Some(compressedCode), _) => LzString.decompressToEncodedURIComponent(compressedCode) | (None, Reason) => initialReContent @@ -1447,6 +1449,7 @@ let make = (~versions: array) => { let onAction = _ => setActionCount(prev => prev > 1000000 ? 0 : prev + 1) let (compilerState, compilerDispatch) = useCompilerManager( ~initialVersion?, + ~initialModuleSystem?, ~initialLang, ~onAction, ~versions, diff --git a/src/common/CompilerManagerHook.res b/src/common/CompilerManagerHook.res index f096afa48..32aa4160d 100644 --- a/src/common/CompilerManagerHook.res +++ b/src/common/CompilerManagerHook.res @@ -242,13 +242,14 @@ type action = | CompileCode(Lang.t, string) | UpdateConfig(Config.t) -let createUrl = (pathName, {code, selected: {compilerVersion}, targetLang}) => { - let params = switch targetLang { +let createUrl = (pathName, ready) => { + let params = switch ready.targetLang { | Res => [] | lang => [("ext", RescriptCompilerApi.Lang.toExt(lang))] } - Array.push(params, ("version", "v" ++ compilerVersion)) - Array.push(params, ("code", code->LzString.compressToEncodedURIComponent)) + Array.push(params, ("version", "v" ++ ready.selected.compilerVersion)) + Array.push(params, ("module", ready.selected.config.module_system)) + Array.push(params, ("code", ready.code->LzString.compressToEncodedURIComponent)) let querystring = params->Array.map(((key, value)) => key ++ "=" ++ value)->Array.join("&") let url = pathName ++ "?" ++ querystring url @@ -267,6 +268,7 @@ let createUrl = (pathName, {code, selected: {compilerVersion}, targetLang}) => { // cases where the output didn't visually change) let useCompilerManager = ( ~initialVersion: option=?, + ~initialModuleSystem="esmodule", ~initialLang: Lang.t=Res, ~onAction: option unit>=?, ~versions: array, @@ -430,7 +432,7 @@ let useCompilerManager = ( // internal compiler state with our playground state. let config = { ...instance->Compiler.getConfig, - module_system: "esmodule", + module_system: initialModuleSystem, ?open_modules, } instance->Compiler.setConfig(config) diff --git a/src/common/CompilerManagerHook.resi b/src/common/CompilerManagerHook.resi index 129f51375..f2880d321 100644 --- a/src/common/CompilerManagerHook.resi +++ b/src/common/CompilerManagerHook.resi @@ -59,6 +59,7 @@ type action = let useCompilerManager: ( ~initialVersion: Semver.t=?, + ~initialModuleSystem: string=?, ~initialLang: Lang.t=?, ~onAction: action => unit=?, ~versions: array, From 4cf1d43782a9a9cacf0a913fa7605ec6a981cc9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Tsnobiladz=C3=A9?= Date: Tue, 12 Nov 2024 14:05:37 +0100 Subject: [PATCH 5/5] on compiler switch use esmodule by default --- src/common/CompilerManagerHook.res | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/common/CompilerManagerHook.res b/src/common/CompilerManagerHook.res index 32aa4160d..ddff4b789 100644 --- a/src/common/CompilerManagerHook.res +++ b/src/common/CompilerManagerHook.res @@ -255,6 +255,8 @@ let createUrl = (pathName, ready) => { url } +let defaultModuleSystem = "esmodule" + // ~initialLang: // The target language the compiler should be set to during // playground initialization. If the compiler doesn't support the language, it @@ -268,7 +270,7 @@ let createUrl = (pathName, ready) => { // cases where the output didn't visually change) let useCompilerManager = ( ~initialVersion: option=?, - ~initialModuleSystem="esmodule", + ~initialModuleSystem=defaultModuleSystem, ~initialLang: Lang.t=Res, ~onAction: option unit>=?, ~versions: array, @@ -485,7 +487,11 @@ let useCompilerManager = ( let apiVersion = apiVersion->Version.fromString let open_modules = getOpenModules(~apiVersion, ~libraries) - let config = {...instance->Compiler.getConfig, ?open_modules} + let config = { + ...instance->Compiler.getConfig, + module_system: defaultModuleSystem, + ?open_modules, + } instance->Compiler.setConfig(config) let selected = {