mirror of
https://github.com/rowtype-yoga/psfp.git
synced 2024-09-11 16:25:36 +03:00
works better
This commit is contained in:
parent
4a3f8f821f
commit
191a78d493
51
client/dist/bundle.js
vendored
51
client/dist/bundle.js
vendored
File diff suppressed because one or more lines are too long
6961
client/package-lock.json
generated
6961
client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -33,13 +33,13 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@material-ui/styles": "^4.4.3",
|
"@material-ui/styles": "^4.4.3",
|
||||||
"@monaco-editor/react": "^1.2.2",
|
"@monaco-editor/react": "^1.2.2",
|
||||||
"purty": "^4.5.1",
|
|
||||||
"react": "^16.9.0",
|
"react": "^16.9.0",
|
||||||
"react-dom": "^16.9.0",
|
"react-dom": "^16.9.0",
|
||||||
"react-hot-loader": "^4.12.15",
|
|
||||||
"smoothscroll-polyfill": "^0.4.4"
|
"smoothscroll-polyfill": "^0.4.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"react-hot-loader": "^4.12.15",
|
||||||
|
"purty": "^4.5.1",
|
||||||
"@babel/core": "^7.6.0",
|
"@babel/core": "^7.6.0",
|
||||||
"@storybook/react": "^5.2.0",
|
"@storybook/react": "^5.2.0",
|
||||||
"@testing-library/react": "^9.1.4",
|
"@testing-library/react": "^9.1.4",
|
||||||
@ -48,11 +48,11 @@
|
|||||||
"deep-equal": "^1.1.0",
|
"deep-equal": "^1.1.0",
|
||||||
"jsdom": "^15.1.1",
|
"jsdom": "^15.1.1",
|
||||||
"jsdom-global": "^3.0.2",
|
"jsdom-global": "^3.0.2",
|
||||||
"purescript": "^0.13.3",
|
"purescript": "^0.13.6",
|
||||||
"purescript-psa": "^0.7.3",
|
"purescript-psa": "^0.7.3",
|
||||||
"purs-loader": "^3.6.0",
|
"purs-loader": "^3.7.0",
|
||||||
"react-svg-loader": "^3.0.3",
|
"react-svg-loader": "^3.0.3",
|
||||||
"spago": "^0.10.0",
|
"spago": "^0.13.1",
|
||||||
"webpack": "^4.41.0",
|
"webpack": "^4.41.0",
|
||||||
"webpack-cli": "^3.3.6",
|
"webpack-cli": "^3.3.6",
|
||||||
"webpack-dev-server": "^3.8.1",
|
"webpack-dev-server": "^3.8.1",
|
||||||
|
@ -121,21 +121,21 @@ let additions =
|
|||||||
let upstream =
|
let upstream =
|
||||||
https://github.com/purescript/package-sets/releases/download/psc-0.13.3-20190920/packages.dhall sha256:53873cf2fc4a343a41f335ee47c1706ecf755ac7c5a336e8eb03ad23165dfd28
|
https://github.com/purescript/package-sets/releases/download/psc-0.13.3-20190920/packages.dhall sha256:53873cf2fc4a343a41f335ee47c1706ecf755ac7c5a336e8eb03ad23165dfd28
|
||||||
|
|
||||||
let overrides =
|
let overrides = {=}
|
||||||
{ react-basic-hooks =
|
-- { react-basic-hooks =
|
||||||
upstream.react-basic-hooks // { version = "v2.0.1" }
|
-- upstream.react-basic-hooks // { version = "v2.0.1" }
|
||||||
, spec-discovery =
|
-- , spec-discovery =
|
||||||
upstream.spec-discovery // { version = "1ca3416e6c0729eca8d5204f22cf0aa09c98df9d" }
|
-- upstream.spec-discovery // { version = "1ca3416e6c0729eca8d5204f22cf0aa09c98df9d" }
|
||||||
, react-basic =
|
-- , react-basic =
|
||||||
upstream.react-basic
|
-- upstream.react-basic
|
||||||
// { repo =
|
-- // { repo =
|
||||||
"https://github.com/i-am-the-slime/purescript-react-basic"
|
-- "https://github.com/i-am-the-slime/purescript-react-basic"
|
||||||
, version =
|
-- , version =
|
||||||
"dda3f711d84cd5dc1817a71ff01f0426b04ed791"
|
-- "dda3f711d84cd5dc1817a71ff01f0426b04ed791"
|
||||||
}
|
-- }
|
||||||
}
|
-- }
|
||||||
|
|
||||||
let additions =
|
let additions =
|
||||||
{ react-testing-library =
|
{ react-testing-library =
|
||||||
{ dependencies =
|
{ dependencies =
|
||||||
[ "aff-promise"
|
[ "aff-promise"
|
||||||
@ -171,19 +171,6 @@ let additions =
|
|||||||
, version =
|
, version =
|
||||||
"7715e8a2c096c480a093a5e0a6df1ece4df5ed2a"
|
"7715e8a2c096c480a093a5e0a6df1ece4df5ed2a"
|
||||||
}
|
}
|
||||||
, matryoshka =
|
|
||||||
{ dependencies =
|
|
||||||
[ "prelude"
|
|
||||||
, "fixed-points"
|
|
||||||
, "free"
|
|
||||||
, "transformers"
|
|
||||||
, "profunctor"
|
|
||||||
]
|
|
||||||
, repo =
|
|
||||||
"https://github.com/slamdata/purescript-matryoshka.git"
|
|
||||||
, version =
|
|
||||||
"caaca2d836d52159ba7963333996286a00428394"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
in upstream // overrides // additions
|
in upstream // overrides // additions
|
||||||
|
@ -9,7 +9,6 @@ You can edit this file as you like.
|
|||||||
, "css"
|
, "css"
|
||||||
, "debug"
|
, "debug"
|
||||||
, "effect"
|
, "effect"
|
||||||
, "matryoshka"
|
|
||||||
, "milkis"
|
, "milkis"
|
||||||
, "psci-support"
|
, "psci-support"
|
||||||
, "pseudo-random"
|
, "pseudo-random"
|
||||||
|
@ -18,29 +18,29 @@ import Theme.Provider (mkThemeProvider)
|
|||||||
import Theme.Styles (makeStyles)
|
import Theme.Styles (makeStyles)
|
||||||
import Theme.Types (CSSTheme)
|
import Theme.Types (CSSTheme)
|
||||||
|
|
||||||
mkContainer ∷ Effect (ReactComponent { theme ∷ CSSTheme, children ∷ Array JSX })
|
mkContainer ∷ Effect (ReactComponent { theme ∷ CSSTheme, kids ∷ Array JSX })
|
||||||
mkContainer = do
|
mkContainer = do
|
||||||
themeProvider <- mkThemeProvider
|
themeProvider <- mkThemeProvider
|
||||||
containerContent <- mkContainerContent
|
containerContent <- mkContainerContent
|
||||||
component "Container" \{ theme, children } -> React.do
|
component "Container" \{ theme, kids } -> React.do
|
||||||
pure
|
pure
|
||||||
$ element themeProvider
|
$ element themeProvider
|
||||||
{ theme
|
{ theme
|
||||||
, children:
|
, children:
|
||||||
[ element containerContent { children }
|
[ element containerContent { kids }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
mkContainerContent ∷ Effect (ReactComponent { children ∷ Array JSX })
|
mkContainerContent ∷ Effect (ReactComponent { kids ∷ Array JSX })
|
||||||
mkContainerContent = do
|
mkContainerContent = do
|
||||||
smoothScrollPolyfill
|
smoothScrollPolyfill
|
||||||
useStyles <-
|
useStyles <-
|
||||||
makeStyles \(theme ∷ CSSTheme) ->
|
makeStyles \(theme ∷ CSSTheme) ->
|
||||||
-- { "@global": cssSafer { "*": { outline: "1px solid red" } }
|
-- { "@global": cssSafer { "*": { outline: "1px solid red" } }
|
||||||
{ container:
|
{ container:
|
||||||
|
--"@global": -- { "*": { outline: "1px solid red" } }
|
||||||
cssSafer
|
cssSafer
|
||||||
{ backgroundColor: theme.backgroundColour
|
{ fontFamily: theme.textFontFamily
|
||||||
, fontFamily: theme.textFontFamily
|
|
||||||
, color: theme.textColour
|
, color: theme.textColour
|
||||||
, display: "grid"
|
, display: "grid"
|
||||||
, transition: "0.2s ease-in-out"
|
, transition: "0.2s ease-in-out"
|
||||||
@ -49,14 +49,14 @@ mkContainerContent = do
|
|||||||
<> "'header header header' "
|
<> "'header header header' "
|
||||||
<> "'nav content content'"
|
<> "'nav content content'"
|
||||||
-- , "footer footer footer"
|
-- , "footer footer footer"
|
||||||
-- , gridTemplateColumns: "max-content auto"
|
, gridTemplateColumns: "max-content auto"
|
||||||
, minWidth: "100%"
|
, width: "100%"
|
||||||
, maxWidth: "100%"
|
, maxHeight: "100%"
|
||||||
}
|
}
|
||||||
, content:
|
, content:
|
||||||
cssSafer
|
cssSafer
|
||||||
{ gridArea: "content"
|
{ gridArea: "content"
|
||||||
, minHeight: "200vh"
|
, backgroundColor: theme.backgroundColour
|
||||||
}
|
}
|
||||||
, icon: cssSafer { fill: "theme.textColour" }
|
, icon: cssSafer { fill: "theme.textColour" }
|
||||||
}
|
}
|
||||||
@ -65,7 +65,7 @@ mkContainerContent = do
|
|||||||
header <- mkHeader
|
header <- mkHeader
|
||||||
sidebarLink <- mkSidebarLink
|
sidebarLink <- mkSidebarLink
|
||||||
editor <- mkCompileEditor
|
editor <- mkCompileEditor
|
||||||
component "ContainerContent" \{ children } -> React.do
|
component "ContainerContent" \{ kids } -> React.do
|
||||||
classes <- useStyles
|
classes <- useStyles
|
||||||
collapsed /\ modifyCollapsed <- useState true
|
collapsed /\ modifyCollapsed <- useState true
|
||||||
editorRef <- useRef Nullable.null
|
editorRef <- useRef Nullable.null
|
||||||
@ -85,7 +85,7 @@ mkContainerContent = do
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
, element header {}
|
, element header {}
|
||||||
, R.div { className: classes.content, children: [ element editor { initialCode } ] <> children }
|
, R.div { className: classes.content, children: [ element editor { initialCode } ] <> kids }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
module Container.Landing where
|
module Container.Landing where
|
||||||
|
|
||||||
import Prelude
|
import Prelude
|
||||||
|
|
||||||
import Button.Component (ButtonType(..), mkButton)
|
import Button.Component (ButtonType(..), mkButton)
|
||||||
import CSS.Safer (cssSafer)
|
import CSS.Safer (cssSafer)
|
||||||
import Data.Foldable (for_)
|
import Data.Foldable (for_)
|
||||||
@ -84,7 +83,7 @@ mkLandingPage = do
|
|||||||
h <- mkH
|
h <- mkH
|
||||||
button <- mkButton
|
button <- mkButton
|
||||||
backgroundImage <- mkLandingPageBackground
|
backgroundImage <- mkLandingPageBackground
|
||||||
component "LandingPage" \{ } -> React.do
|
component "LandingPage" \{} -> React.do
|
||||||
classes <- useStyles
|
classes <- useStyles
|
||||||
theme <- useTheme
|
theme <- useTheme
|
||||||
ref <- useRef null
|
ref <- useRef null
|
||||||
@ -109,16 +108,17 @@ mkLandingPage = do
|
|||||||
, children:
|
, children:
|
||||||
[ element button
|
[ element button
|
||||||
{ buttonProps:
|
{ buttonProps:
|
||||||
{ onClick: handler_ do
|
{ onClick:
|
||||||
maybeNode <- readRefMaybe ref
|
handler_ do
|
||||||
for_ (maybeNode >>= HTMLElement.fromNode) \n -> do
|
maybeNode <- readRefMaybe ref
|
||||||
height <- getBoundingClientRect n <#> _.height
|
for_ (maybeNode >>= HTMLElement.fromNode) \n -> do
|
||||||
win <- window
|
height <- getBoundingClientRect n <#> _.height
|
||||||
runEffectFn1 ((unsafeCoerce win).scrollTo)
|
win <- window
|
||||||
{ top: height, left: 0, behavior: "smooth"}
|
runEffectFn1 ((unsafeCoerce win).scrollTo)
|
||||||
|
{ top: height, left: 0, behavior: "smooth" }
|
||||||
}
|
}
|
||||||
, buttonType: HighlightedButton
|
, buttonType: HighlightedButton
|
||||||
, children: [ R.text buttonText ]
|
, kids: [ R.text buttonText ]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
module Example (main) where
|
module Example (main) where
|
||||||
|
|
||||||
import Prelude
|
import Prelude
|
||||||
|
|
||||||
import Container.Component (mkContainer)
|
import Container.Component (mkContainer)
|
||||||
import Data.Maybe (fromJust)
|
import Data.Maybe (fromJust)
|
||||||
import Effect (Effect)
|
import Effect (Effect)
|
||||||
@ -16,21 +15,24 @@ import Web.HTML (window) as DOM
|
|||||||
import Web.HTML.HTMLDocument (toNonElementParentNode) as DOM
|
import Web.HTML.HTMLDocument (toNonElementParentNode) as DOM
|
||||||
import Web.HTML.Window (document) as DOM
|
import Web.HTML.Window (document) as DOM
|
||||||
|
|
||||||
|
|
||||||
main ∷ Effect Unit
|
main ∷ Effect Unit
|
||||||
main = do
|
main = do
|
||||||
container <- mkContainer
|
container <- mkContainer
|
||||||
let appEl = element container { theme: fromTheme darkTheme, children: [] }
|
let
|
||||||
|
appEl = element container { theme: fromTheme darkTheme, kids: [] }
|
||||||
if isServerSide
|
if isServerSide then
|
||||||
then void (log (renderToString appEl))
|
void (log (renderToString appEl))
|
||||||
else void do
|
else
|
||||||
window <- DOM.window
|
void do
|
||||||
document <- DOM.document window
|
window <- DOM.window
|
||||||
let node = DOM.toNonElementParentNode document
|
document <- DOM.document window
|
||||||
elem <- DOM.getElementById "app" node
|
let
|
||||||
let element' = unsafePartial (fromJust elem)
|
node = DOM.toNonElementParentNode document
|
||||||
ReactDOM.render appEl element'
|
elem <- DOM.getElementById "app" node
|
||||||
|
let
|
||||||
|
element' = unsafePartial (fromJust elem)
|
||||||
|
ReactDOM.render appEl element'
|
||||||
|
|
||||||
foreign import isServerSide ∷ Boolean
|
foreign import isServerSide ∷ Boolean
|
||||||
|
|
||||||
foreign import renderToString ∷ JSX -> String
|
foreign import renderToString ∷ JSX -> String
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
module ContainerStories where
|
module ContainerStories where
|
||||||
|
|
||||||
import Prelude hiding (add)
|
import Prelude hiding (add)
|
||||||
|
|
||||||
import Container.Component (mkContainer)
|
import Container.Component (mkContainer)
|
||||||
import Decorator.FullScreen (fullScreenDecorator)
|
import Decorator.FullScreen (fullScreenDecorator)
|
||||||
import Effect (Effect)
|
import Effect (Effect)
|
||||||
@ -23,5 +22,5 @@ stories = do
|
|||||||
pure
|
pure
|
||||||
$ element container
|
$ element container
|
||||||
{ theme
|
{ theme
|
||||||
, children: []
|
, kids: []
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
module Test.Main where
|
module Test.Main where
|
||||||
|
|
||||||
import Prelude
|
import Prelude
|
||||||
|
|
||||||
import Effect (Effect)
|
import Effect (Effect)
|
||||||
import Effect.Class.Console (log)
|
import Effect.Class.Console (log)
|
||||||
|
|
||||||
|
@ -1,9 +1,16 @@
|
|||||||
'use strict';
|
"use strict";
|
||||||
const merge = require('webpack-merge');
|
const merge = require("webpack-merge");
|
||||||
const common = require('./webpack.common.js');
|
const common = require("./webpack.common.js");
|
||||||
const path = require('path');
|
const path = require("path");
|
||||||
|
|
||||||
module.exports = merge(common, {
|
module.exports = merge(common, {
|
||||||
entry: './src/entrypoint.js',
|
entry: "./src/entrypoint.js",
|
||||||
mode: 'production'
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
// Only resolve react and dom once
|
||||||
|
react: path.resolve("./node_modules/react"),
|
||||||
|
"react-dom": path.resolve("./node_modules/react-dom")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mode: "production"
|
||||||
});
|
});
|
||||||
|
7119
components/package-lock.json
generated
7119
components/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -30,16 +30,15 @@
|
|||||||
"url": "https://github.com/i-am-the-slime/psfp/issues"
|
"url": "https://github.com/i-am-the-slime/psfp/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/i-am-the-slime/psfp#readme",
|
"homepage": "https://github.com/i-am-the-slime/psfp#readme",
|
||||||
"dependencies": {
|
"dependencies": {},
|
||||||
|
"devDependencies": {
|
||||||
"@material-ui/styles": "^4.4.3",
|
"@material-ui/styles": "^4.4.3",
|
||||||
"@monaco-editor/react": "^1.2.2",
|
"@monaco-editor/react": "^1.2.2",
|
||||||
"purty": "^4.5.1",
|
"purty": "^4.5.1",
|
||||||
"react": "^16.9.0",
|
"react": "^16.9.0",
|
||||||
"react-dom": "^16.9.0",
|
"react-dom": "^16.9.0",
|
||||||
"react-hot-loader": "^4.12.15",
|
"react-hot-loader": "^4.12.15",
|
||||||
"smoothscroll-polyfill": "^0.4.4"
|
"smoothscroll-polyfill": "^0.4.4",
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@babel/core": "^7.6.0",
|
"@babel/core": "^7.6.0",
|
||||||
"@storybook/react": "^5.2.0",
|
"@storybook/react": "^5.2.0",
|
||||||
"@testing-library/react": "^9.1.4",
|
"@testing-library/react": "^9.1.4",
|
||||||
|
@ -33,7 +33,7 @@ mkButton ∷
|
|||||||
Lacks "key" attrs =>
|
Lacks "key" attrs =>
|
||||||
Effect
|
Effect
|
||||||
( ReactComponent
|
( ReactComponent
|
||||||
{ children ∷ Array JSX
|
{ kids ∷ Array JSX
|
||||||
, buttonType ∷ ButtonType
|
, buttonType ∷ ButtonType
|
||||||
, buttonProps ∷ Record attrs
|
, buttonProps ∷ Record attrs
|
||||||
}
|
}
|
||||||
@ -135,7 +135,7 @@ mkButton = do
|
|||||||
pure $ increaseContrast bg tc # toHexString
|
pure $ increaseContrast bg tc # toHexString
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
component "Button" \{ children, buttonType, buttonProps } -> React.do
|
component "Button" \{ kids, buttonType, buttonProps } -> React.do
|
||||||
rawClasses <- useStyles
|
rawClasses <- useStyles
|
||||||
let
|
let
|
||||||
classes = flip classNames rawClasses
|
classes = flip classNames rawClasses
|
||||||
@ -147,7 +147,7 @@ mkButton = do
|
|||||||
, guard (buttonType == HighlightedButton) _.highlightedButton
|
, guard (buttonType == HighlightedButton) _.highlightedButton
|
||||||
]
|
]
|
||||||
, disabled: buttonType == DisabledButton
|
, disabled: buttonType == DisabledButton
|
||||||
, children
|
, children: kids
|
||||||
}
|
}
|
||||||
`union`
|
`union`
|
||||||
buttonProps
|
buttonProps
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
module Card.Component where
|
module Card.Component where
|
||||||
|
|
||||||
import Prelude
|
import Prelude
|
||||||
|
|
||||||
import CSS.Safer (cssSafer)
|
import CSS.Safer (cssSafer)
|
||||||
import Effect (Effect)
|
import Effect (Effect)
|
||||||
import React.Basic (JSX)
|
import React.Basic (JSX)
|
||||||
@ -14,7 +13,7 @@ import Theme.Types (CSSTheme)
|
|||||||
mkCard ∷
|
mkCard ∷
|
||||||
Effect
|
Effect
|
||||||
( ReactComponent
|
( ReactComponent
|
||||||
{ children ∷ Array JSX
|
{ kids ∷ Array JSX
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
mkCard = do
|
mkCard = do
|
||||||
@ -26,26 +25,27 @@ mkCard = do
|
|||||||
, color: theme.textColour
|
, color: theme.textColour
|
||||||
, margin: "20px"
|
, margin: "20px"
|
||||||
, boxShadow:
|
, boxShadow:
|
||||||
"1px 1px 20px rgba(0,0,0,0." <>
|
"1px 1px 20px rgba(0,0,0,0."
|
||||||
(if theme.isLight then "17" else "43") <> ")"
|
<> (if theme.isLight then "17" else "43")
|
||||||
|
<> ")"
|
||||||
, borderRadius: "5px"
|
, borderRadius: "5px"
|
||||||
, padding: "36px 40px 32px 40px"
|
, padding: "36px 40px 32px 40px"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
component "Card" \{ children } -> React.do
|
component "Card" \{ kids } -> React.do
|
||||||
rawClasses <- useStyles
|
rawClasses <- useStyles
|
||||||
let
|
let
|
||||||
classes = flip classNames rawClasses
|
classes = flip classNames rawClasses
|
||||||
pure
|
pure
|
||||||
$ R.div
|
$ R.div
|
||||||
{ className: classes [ _.card ]
|
{ className: classes [ _.card ]
|
||||||
, children
|
, children: kids
|
||||||
}
|
}
|
||||||
|
|
||||||
mkCardTitle ∷
|
mkCardTitle ∷
|
||||||
Effect
|
Effect
|
||||||
( ReactComponent
|
( ReactComponent
|
||||||
{ children ∷ Array JSX
|
{ kids ∷ Array JSX
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
mkCardTitle = do
|
mkCardTitle = do
|
||||||
@ -60,20 +60,20 @@ mkCardTitle = do
|
|||||||
, padding: "4px 8px"
|
, padding: "4px 8px"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
component "CardTitle" \{ children } -> React.do
|
component "CardTitle" \{ kids } -> React.do
|
||||||
rawClasses <- useStyles
|
rawClasses <- useStyles
|
||||||
let
|
let
|
||||||
classes = flip classNames rawClasses
|
classes = flip classNames rawClasses
|
||||||
pure
|
pure
|
||||||
$ R.div
|
$ R.div
|
||||||
{ className: classes [ _.cardtitle ]
|
{ className: classes [ _.cardtitle ]
|
||||||
, children
|
, children: kids
|
||||||
}
|
}
|
||||||
|
|
||||||
mkCardSubtitle ∷
|
mkCardSubtitle ∷
|
||||||
Effect
|
Effect
|
||||||
( ReactComponent
|
( ReactComponent
|
||||||
{ children ∷ Array JSX
|
{ kids ∷ Array JSX
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
mkCardSubtitle = do
|
mkCardSubtitle = do
|
||||||
@ -89,20 +89,20 @@ mkCardSubtitle = do
|
|||||||
, padding: "4px 8px 22px 8px"
|
, padding: "4px 8px 22px 8px"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
component "CardSubtitle" \{ children } -> React.do
|
component "CardSubtitle" \{ kids } -> React.do
|
||||||
rawClasses <- useStyles
|
rawClasses <- useStyles
|
||||||
let
|
let
|
||||||
classes = flip classNames rawClasses
|
classes = flip classNames rawClasses
|
||||||
pure
|
pure
|
||||||
$ R.div
|
$ R.div
|
||||||
{ className: classes [ _.cardtitle ]
|
{ className: classes [ _.cardtitle ]
|
||||||
, children
|
, children: kids
|
||||||
}
|
}
|
||||||
|
|
||||||
mkCardContent ∷
|
mkCardContent ∷
|
||||||
Effect
|
Effect
|
||||||
( ReactComponent
|
( ReactComponent
|
||||||
{ children ∷ Array JSX
|
{ kids ∷ Array JSX
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
mkCardContent = do
|
mkCardContent = do
|
||||||
@ -120,12 +120,12 @@ mkCardContent = do
|
|||||||
, padding: "4px 8px 22px 8px"
|
, padding: "4px 8px 22px 8px"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
component "CardContent" \{ children } -> React.do
|
component "CardContent" \{ kids } -> React.do
|
||||||
rawClasses <- useStyles
|
rawClasses <- useStyles
|
||||||
let
|
let
|
||||||
classes = flip classNames rawClasses
|
classes = flip classNames rawClasses
|
||||||
pure
|
pure
|
||||||
$ R.div
|
$ R.div
|
||||||
{ className: classes [ _.cardContent ]
|
{ className: classes [ _.cardContent ]
|
||||||
, children
|
, children: kids
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ mkCompileEditor = do
|
|||||||
$ fragment
|
$ fragment
|
||||||
[ element button
|
[ element button
|
||||||
{ buttonType: PlainButton
|
{ buttonType: PlainButton
|
||||||
, children: [ R.text "Compile" ]
|
, kids: [ R.text "Compile" ]
|
||||||
, buttonProps:
|
, buttonProps:
|
||||||
{ onClick:
|
{ onClick:
|
||||||
handler_ do
|
handler_ do
|
||||||
@ -65,7 +65,7 @@ mkCompileEditor = do
|
|||||||
Right r -> r.stdout
|
Right r -> r.stdout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
, element card { children: [ R.text compileResult ] }
|
, element card { kids: [ R.text compileResult ] }
|
||||||
, R.div { children: [ element editor { onLoad } ], style: css { height: "100%" } }
|
, R.div { children: [ element editor { onLoad } ], style: css { height: "100%" } }
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -11,10 +11,10 @@ import Effect.Uncurried (EffectFn2, mkEffectFn2)
|
|||||||
import Foreign (Foreign, unsafeToForeign)
|
import Foreign (Foreign, unsafeToForeign)
|
||||||
import Prim.Row (class Union)
|
import Prim.Row (class Union)
|
||||||
import React.Basic (JSX, ReactComponent, element, fragment)
|
import React.Basic (JSX, ReactComponent, element, fragment)
|
||||||
|
import React.Basic.DOM as R
|
||||||
import React.Basic.Hooks (component)
|
import React.Basic.Hooks (component)
|
||||||
import React.Basic.Hooks as React
|
import React.Basic.Hooks as React
|
||||||
import React.Basic.Hooks.Aff (useAff)
|
import React.Basic.Hooks.Aff (useAff)
|
||||||
import React.Helpers (wrapperDiv)
|
|
||||||
import Theme.Styles (makeStyles, useTheme)
|
import Theme.Styles (makeStyles, useTheme)
|
||||||
import Theme.Types (CSSTheme)
|
import Theme.Types (CSSTheme)
|
||||||
import Web.DOM (Node)
|
import Web.DOM (Node)
|
||||||
@ -92,10 +92,9 @@ mkEditor = do
|
|||||||
cssSafer
|
cssSafer
|
||||||
{ margin: "0"
|
{ margin: "0"
|
||||||
, boxSizing: "border-box"
|
, boxSizing: "border-box"
|
||||||
, padding: "35px 40px"
|
|
||||||
, width: "100%"
|
, width: "100%"
|
||||||
, height: "100%"
|
, height: "200px"
|
||||||
, borderRadius: "32px"
|
, overflowY: "hidden"
|
||||||
, backgroundColor: theme.backgroundColour
|
, backgroundColor: theme.backgroundColour
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,25 +106,28 @@ mkEditor = do
|
|||||||
themeName = if theme.isLight then lightThemeName else darkThemeName
|
themeName = if theme.isLight then lightThemeName else darkThemeName
|
||||||
pure
|
pure
|
||||||
$ fragment
|
$ fragment
|
||||||
[ wrapperDiv { className: classes.wrapper }
|
[ R.div
|
||||||
$ element editor
|
{ className: classes.wrapper
|
||||||
{ theme: themeName
|
, children:
|
||||||
, options:
|
[ element editor
|
||||||
unsafeToForeign
|
{ theme: themeName
|
||||||
{ fontFamily: "PragmataPro"
|
, options:
|
||||||
, fontLigatures: true
|
unsafeToForeign
|
||||||
, fontSize: "16pt"
|
{ fontFamily: "PragmataPro"
|
||||||
, lineNumbers: "off"
|
, fontLigatures: true
|
||||||
, glyphMargin: false
|
, fontSize: "16pt"
|
||||||
, folding: false
|
, lineNumbers: "off"
|
||||||
, lineDecorationsWidth: 0
|
, glyphMargin: false
|
||||||
, lineNumbersMinChars: 0
|
, folding: false
|
||||||
, minimap: { enabled: false }
|
, lineDecorationsWidth: 0
|
||||||
, automaticLayout: true
|
, lineNumbersMinChars: 0
|
||||||
}
|
, minimap: { enabled: false }
|
||||||
, language: "purescript"
|
}
|
||||||
-- https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-custom-languages
|
, language: "purescript"
|
||||||
, editorDidMount:
|
-- https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-custom-languages
|
||||||
mkEffectFn2 \_ -> onLoad
|
, editorDidMount:
|
||||||
}
|
mkEffectFn2 \_ -> onLoad
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
@ -1,156 +0,0 @@
|
|||||||
module React.Helpers where
|
|
||||||
|
|
||||||
import Prelude
|
|
||||||
import Data.Nullable (Nullable)
|
|
||||||
import Data.Symbol (SProxy(..))
|
|
||||||
import Foreign.Object (Object)
|
|
||||||
import Prim.Row (class Lacks, class Union)
|
|
||||||
import React.Basic (JSX)
|
|
||||||
import React.Basic.DOM (CSS)
|
|
||||||
import React.Basic.DOM as R
|
|
||||||
import React.Basic.Events (EventHandler)
|
|
||||||
import React.Basic.Hooks (Ref)
|
|
||||||
import Record (insert)
|
|
||||||
import Web.DOM (Node)
|
|
||||||
|
|
||||||
wrapperDiv ∷
|
|
||||||
∀ attrs attrs_.
|
|
||||||
Lacks "children" attrs =>
|
|
||||||
Union attrs attrs_ Props_div_no_children =>
|
|
||||||
{ | attrs } ->
|
|
||||||
JSX ->
|
|
||||||
JSX
|
|
||||||
wrapperDiv props child = R.div $ insert (SProxy ∷ _ "children") [ child ] props
|
|
||||||
|
|
||||||
type Props_div_no_children
|
|
||||||
= ( _data ∷ Object String
|
|
||||||
, about ∷ String
|
|
||||||
, acceptCharset ∷ String
|
|
||||||
, accessKey ∷ String
|
|
||||||
, allowFullScreen ∷ Boolean
|
|
||||||
, allowTransparency ∷ Boolean
|
|
||||||
, autoComplete ∷ Boolean
|
|
||||||
, autoFocus ∷ Boolean
|
|
||||||
, autoPlay ∷ Boolean
|
|
||||||
, capture ∷ Boolean
|
|
||||||
, cellPadding ∷ String
|
|
||||||
, cellSpacing ∷ String
|
|
||||||
, charSet ∷ String
|
|
||||||
, classID ∷ String
|
|
||||||
, className ∷ String
|
|
||||||
, colSpan ∷ Int
|
|
||||||
, contentEditable ∷ Boolean
|
|
||||||
, contextMenu ∷ String
|
|
||||||
, crossOrigin ∷ String
|
|
||||||
, dangerouslySetInnerHTML ∷ { __html ∷ String }
|
|
||||||
, datatype ∷ String
|
|
||||||
, dateTime ∷ String
|
|
||||||
, dir ∷ String
|
|
||||||
, draggable ∷ Boolean
|
|
||||||
, encType ∷ String
|
|
||||||
, formAction ∷ String
|
|
||||||
, formEncType ∷ String
|
|
||||||
, formMethod ∷ String
|
|
||||||
, formNoValidate ∷ Boolean
|
|
||||||
, formTarget ∷ String
|
|
||||||
, frameBorder ∷ String
|
|
||||||
, hidden ∷ Boolean
|
|
||||||
, hrefLang ∷ String
|
|
||||||
, htmlFor ∷ String
|
|
||||||
, httpEquiv ∷ String
|
|
||||||
, icon ∷ String
|
|
||||||
, id ∷ String
|
|
||||||
, inlist ∷ String
|
|
||||||
, inputMode ∷ String
|
|
||||||
, is ∷ String
|
|
||||||
, itemID ∷ String
|
|
||||||
, itemProp ∷ String
|
|
||||||
, itemRef ∷ String
|
|
||||||
, itemScope ∷ Boolean
|
|
||||||
, itemType ∷ String
|
|
||||||
, key ∷ String
|
|
||||||
, keyParams ∷ String
|
|
||||||
, keyType ∷ String
|
|
||||||
, lang ∷ String
|
|
||||||
, marginHeight ∷ String
|
|
||||||
, marginWidth ∷ String
|
|
||||||
, maxLength ∷ Int
|
|
||||||
, mediaGroup ∷ String
|
|
||||||
, minLength ∷ Int
|
|
||||||
, noValidate ∷ Boolean
|
|
||||||
, onAnimationEnd ∷ EventHandler
|
|
||||||
, onAnimationIteration ∷ EventHandler
|
|
||||||
, onAnimationStart ∷ EventHandler
|
|
||||||
, onBlur ∷ EventHandler
|
|
||||||
, onClick ∷ EventHandler
|
|
||||||
, onCompositionEnd ∷ EventHandler
|
|
||||||
, onCompositionStart ∷ EventHandler
|
|
||||||
, onCompositionUpdate ∷ EventHandler
|
|
||||||
, onContextMenu ∷ EventHandler
|
|
||||||
, onCopy ∷ EventHandler
|
|
||||||
, onCut ∷ EventHandler
|
|
||||||
, onDoubleClick ∷ EventHandler
|
|
||||||
, onDrag ∷ EventHandler
|
|
||||||
, onDragEnd ∷ EventHandler
|
|
||||||
, onDragEnter ∷ EventHandler
|
|
||||||
, onDragExit ∷ EventHandler
|
|
||||||
, onDragLeave ∷ EventHandler
|
|
||||||
, onDragOver ∷ EventHandler
|
|
||||||
, onDragStart ∷ EventHandler
|
|
||||||
, onDrop ∷ EventHandler
|
|
||||||
, onFocus ∷ EventHandler
|
|
||||||
, onGotPointerCapture ∷ EventHandler
|
|
||||||
, onInvalid ∷ EventHandler
|
|
||||||
, onKeyDown ∷ EventHandler
|
|
||||||
, onKeyPress ∷ EventHandler
|
|
||||||
, onKeyUp ∷ EventHandler
|
|
||||||
, onLostPointerCapture ∷ EventHandler
|
|
||||||
, onMouseDown ∷ EventHandler
|
|
||||||
, onMouseEnter ∷ EventHandler
|
|
||||||
, onMouseLeave ∷ EventHandler
|
|
||||||
, onMouseMove ∷ EventHandler
|
|
||||||
, onMouseOut ∷ EventHandler
|
|
||||||
, onMouseOver ∷ EventHandler
|
|
||||||
, onMouseUp ∷ EventHandler
|
|
||||||
, onPaste ∷ EventHandler
|
|
||||||
, onPointerCancel ∷ EventHandler
|
|
||||||
, onPointerDown ∷ EventHandler
|
|
||||||
, onPointerEnter ∷ EventHandler
|
|
||||||
, onPointerLeave ∷ EventHandler
|
|
||||||
, onPointerMove ∷ EventHandler
|
|
||||||
, onPointerOut ∷ EventHandler
|
|
||||||
, onPointerOver ∷ EventHandler
|
|
||||||
, onPointerUp ∷ EventHandler
|
|
||||||
, onSelect ∷ EventHandler
|
|
||||||
, onSubmit ∷ EventHandler
|
|
||||||
, onTouchCancel ∷ EventHandler
|
|
||||||
, onTouchEnd ∷ EventHandler
|
|
||||||
, onTouchMove ∷ EventHandler
|
|
||||||
, onTouchStart ∷ EventHandler
|
|
||||||
, onTransitionEnd ∷ EventHandler
|
|
||||||
, onWheel ∷ EventHandler
|
|
||||||
, prefix ∷ String
|
|
||||||
, property ∷ String
|
|
||||||
, radioGroup ∷ String
|
|
||||||
, readOnly ∷ Boolean
|
|
||||||
, ref ∷ Ref (Nullable Node)
|
|
||||||
, resource ∷ String
|
|
||||||
, role ∷ String
|
|
||||||
, rowSpan ∷ Int
|
|
||||||
, scoped ∷ Boolean
|
|
||||||
, seamless ∷ Boolean
|
|
||||||
, security ∷ String
|
|
||||||
, spellCheck ∷ Boolean
|
|
||||||
, srcDoc ∷ JSX
|
|
||||||
, srcLang ∷ String
|
|
||||||
, srcSet ∷ String
|
|
||||||
, style ∷ CSS
|
|
||||||
, suppressContentEditableWarning ∷ Boolean
|
|
||||||
, tabIndex ∷ Int
|
|
||||||
, title ∷ String
|
|
||||||
, typeof ∷ String
|
|
||||||
, unselectable ∷ Boolean
|
|
||||||
, useMap ∷ String
|
|
||||||
, vocab ∷ String
|
|
||||||
, wmode ∷ String
|
|
||||||
)
|
|
@ -1,7 +1,7 @@
|
|||||||
'use strict'
|
"use strict";
|
||||||
|
|
||||||
var styles = require("@material-ui/styles");
|
var styles = require("@material-ui/styles");
|
||||||
|
|
||||||
exports.mkThemeProviderImpl = function() {
|
exports.mkThemeProviderImpl = function() {
|
||||||
return styles.ThemeProvider;
|
return styles.ThemeProvider;
|
||||||
}
|
};
|
||||||
|
@ -121,18 +121,7 @@ let additions =
|
|||||||
let upstream =
|
let upstream =
|
||||||
https://github.com/purescript/package-sets/releases/download/psc-0.13.6-20200123/packages.dhall sha256:687bb9a2d38f2026a89772c47390d02939340b01e31aaa22de9247eadd64af05
|
https://github.com/purescript/package-sets/releases/download/psc-0.13.6-20200123/packages.dhall sha256:687bb9a2d38f2026a89772c47390d02939340b01e31aaa22de9247eadd64af05
|
||||||
|
|
||||||
let overrides =
|
let overrides = {=}
|
||||||
{ react-basic-hooks = upstream.react-basic-hooks // { version = "v2.0.1" }
|
|
||||||
, spec-discovery =
|
|
||||||
upstream.spec-discovery
|
|
||||||
// { version = "1ca3416e6c0729eca8d5204f22cf0aa09c98df9d" }
|
|
||||||
, react-basic =
|
|
||||||
upstream.react-basic
|
|
||||||
// { repo =
|
|
||||||
"https://github.com/i-am-the-slime/purescript-react-basic"
|
|
||||||
, version = "dda3f711d84cd5dc1817a71ff01f0426b04ed791"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let additions =
|
let additions =
|
||||||
{ react-testing-library =
|
{ react-testing-library =
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
module Main where
|
module Main where
|
||||||
|
|
||||||
import Effect.Class.Console (log)
|
import Batteries
|
||||||
|
|
||||||
main = log "Uh-oh"
|
main :: Effect Unit
|
||||||
|
main = log "Hello, World!"
|
||||||
|
File diff suppressed because one or more lines are too long
@ -10,10 +10,10 @@ import Effect.Ref (Ref)
|
|||||||
import Effect.Ref as Ref
|
import Effect.Ref as Ref
|
||||||
import JobQueue (EnqueueResult(..), NewJob(..), QueueParams, ResourcePool(..), mkQueue)
|
import JobQueue (EnqueueResult(..), NewJob(..), QueueParams, ResourcePool(..), mkQueue)
|
||||||
import JobQueue as Q
|
import JobQueue as Q
|
||||||
import Main (execCommand)
|
|
||||||
import Playground.Playground (Folder(..))
|
import Playground.Playground (Folder(..))
|
||||||
import Test.Spec (Spec, describe, it)
|
import Test.Spec (Spec, describe, it)
|
||||||
import Test.Spec.Assertions (shouldEqual, shouldNotEqual)
|
import Test.Spec.Assertions (shouldEqual, shouldNotEqual)
|
||||||
|
import PscIdeClient (execCommand)
|
||||||
|
|
||||||
params ∷ QueueParams
|
params ∷ QueueParams
|
||||||
params =
|
params =
|
||||||
|
@ -2,16 +2,16 @@ module Main where
|
|||||||
|
|
||||||
import Prelude
|
import Prelude
|
||||||
|
|
||||||
|
import Control.Parallel (parTraverse)
|
||||||
import Data.Array ((..))
|
import Data.Array ((..))
|
||||||
import Data.Either (Either(..))
|
import Data.Either (Either(..))
|
||||||
import Data.Int (fromString)
|
import Data.Int (fromString)
|
||||||
import Data.Maybe (Maybe(..), fromMaybe)
|
import Data.Maybe (Maybe, fromMaybe)
|
||||||
import Data.Newtype (un)
|
import Data.Newtype (un)
|
||||||
import Data.Posix.Signal (Signal(..))
|
|
||||||
import Data.Time.Duration (Seconds(..), fromDuration)
|
import Data.Time.Duration (Seconds(..), fromDuration)
|
||||||
import Data.Traversable (for)
|
import Data.Traversable (for)
|
||||||
import Effect (Effect)
|
import Effect (Effect)
|
||||||
import Effect.Aff (Aff, effectCanceler, launchAff_, makeAff, parallel, sequential)
|
import Effect.Aff (Aff, launchAff_)
|
||||||
import Effect.Aff.Class (liftAff)
|
import Effect.Aff.Class (liftAff)
|
||||||
import Effect.Class (class MonadEffect, liftEffect)
|
import Effect.Class (class MonadEffect, liftEffect)
|
||||||
import Effect.Class.Console (info, log)
|
import Effect.Class.Console (info, log)
|
||||||
@ -21,7 +21,7 @@ import JobQueue as Q
|
|||||||
import Middleware.JsonBodyParser (jsonBodyParser)
|
import Middleware.JsonBodyParser (jsonBodyParser)
|
||||||
import Node.Buffer (Buffer)
|
import Node.Buffer (Buffer)
|
||||||
import Node.Buffer as Buffer
|
import Node.Buffer as Buffer
|
||||||
import Node.ChildProcess (ExecResult, defaultExecOptions, exec, kill, pid)
|
import Node.ChildProcess (ExecResult)
|
||||||
import Node.Encoding (Encoding(..))
|
import Node.Encoding (Encoding(..))
|
||||||
import Node.Express.App (App, listenHttp, listenHttps, use, useExternal)
|
import Node.Express.App (App, listenHttp, listenHttps, use, useExternal)
|
||||||
import Node.Express.App as E
|
import Node.Express.App as E
|
||||||
@ -36,7 +36,7 @@ import Node.HTTP (Server)
|
|||||||
import Node.OS (numCpus)
|
import Node.OS (numCpus)
|
||||||
import Node.Process (lookupEnv)
|
import Node.Process (lookupEnv)
|
||||||
import Playground.Playground (Folder(..), copy)
|
import Playground.Playground (Folder(..), copy)
|
||||||
import PscIdeClient (PscIdeConnection, compileCode, getFolder, mkConnection)
|
import PscIdeClient (PscIdeConnection, compileCode, getFolder, mkConnection, execCommand)
|
||||||
import Shared.Json (readAff)
|
import Shared.Json (readAff)
|
||||||
import Shared.Models.Body (CompileRequest, RunResult, CompileResult)
|
import Shared.Models.Body (CompileRequest, RunResult, CompileResult)
|
||||||
import Shared.Models.Body as Body
|
import Shared.Models.Body as Body
|
||||||
@ -61,14 +61,6 @@ asErrorWithCode = read_ <<< unsafeToForeign
|
|||||||
runCode ∷ Folder -> Aff ExecResult
|
runCode ∷ Folder -> Aff ExecResult
|
||||||
runCode folder = execCommand folder "node run.js"
|
runCode folder = execCommand folder "node run.js"
|
||||||
|
|
||||||
execCommand ∷ Folder -> String -> Aff ExecResult
|
|
||||||
execCommand folder command =
|
|
||||||
makeAff \callback -> do
|
|
||||||
let
|
|
||||||
options = defaultExecOptions { cwd = Just (un Folder folder) }
|
|
||||||
childProcess <- exec command options (callback <<< Right)
|
|
||||||
pure $ effectCanceler ((log $ "Killing " <> show (pid childProcess)) *> kill SIGKILL childProcess)
|
|
||||||
|
|
||||||
compileAndRunJob ∷ CompileRequest -> (Handler -> Aff Unit) -> NewJob PscIdeConnection
|
compileAndRunJob ∷ CompileRequest -> (Handler -> Aff Unit) -> NewJob PscIdeConnection
|
||||||
compileAndRunJob json handle =
|
compileAndRunJob json handle =
|
||||||
NewJob \jobId conn -> do
|
NewJob \jobId conn -> do
|
||||||
@ -117,13 +109,14 @@ main = do
|
|||||||
launchAff_ do
|
launchAff_ do
|
||||||
cpus <- numCpus # liftEffect
|
cpus <- numCpus # liftEffect
|
||||||
let
|
let
|
||||||
poolSize = max 2 (cpus - 1) -- use at least 2
|
poolSize = max 2 (cpus / 2) -- use at least 2
|
||||||
|
|
||||||
mkFolder = Folder <<< (destFolder <> _) <<< show
|
mkFolder = Folder <<< (destFolder <> _) <<< show
|
||||||
|
|
||||||
connections <- for (0 .. poolSize) \n -> do
|
connections <- (1 .. poolSize) # parTraverse \n -> do
|
||||||
let folder = mkFolder n
|
let folder = mkFolder n
|
||||||
port = 14100 + n
|
port = 14100 + n
|
||||||
|
log $ "Copying to folder " <> (un Folder folder)
|
||||||
copy srcFolder (un Folder folder)
|
copy srcFolder (un Folder folder)
|
||||||
mkConnection folder port
|
mkConnection folder port
|
||||||
|
|
||||||
|
@ -1,23 +1,16 @@
|
|||||||
module PscIdeClient where
|
module PscIdeClient where
|
||||||
|
|
||||||
import Prelude
|
import Prelude
|
||||||
|
|
||||||
import Data.Array as Array
|
|
||||||
import Data.Either (Either(..), either)
|
import Data.Either (Either(..), either)
|
||||||
import Data.Foldable (intercalate)
|
|
||||||
import Data.Maybe (Maybe(..))
|
import Data.Maybe (Maybe(..))
|
||||||
import Data.Newtype (class Newtype, un, unwrap)
|
import Data.Newtype (class Newtype, un, unwrap)
|
||||||
import Data.Posix.Signal (Signal(..))
|
import Data.Posix.Signal (Signal(..))
|
||||||
import Data.String.Utils (endsWith)
|
import Data.String.Utils (endsWith)
|
||||||
import Debug.Trace (spy)
|
|
||||||
import Effect (Effect)
|
|
||||||
import Effect.Aff (Aff, Canceler, effectCanceler, makeAff)
|
import Effect.Aff (Aff, Canceler, effectCanceler, makeAff)
|
||||||
import Effect.Class (liftEffect)
|
import Effect.Class (liftEffect)
|
||||||
import Effect.Class.Console (log)
|
import Effect.Class.Console (log)
|
||||||
import Effect.Exception (message)
|
|
||||||
import Effect.Ref (Ref)
|
import Effect.Ref (Ref)
|
||||||
import Effect.Ref as Ref
|
import Effect.Ref as Ref
|
||||||
import Foreign (renderForeignError)
|
|
||||||
import Node.Buffer as Buf
|
import Node.Buffer as Buf
|
||||||
import Node.ChildProcess (ChildProcess)
|
import Node.ChildProcess (ChildProcess)
|
||||||
import Node.ChildProcess as CP
|
import Node.ChildProcess as CP
|
||||||
@ -26,8 +19,7 @@ import Node.FS.Aff (writeTextFile)
|
|||||||
import Node.Net.Socket (Socket)
|
import Node.Net.Socket (Socket)
|
||||||
import Node.Net.Socket as Socket
|
import Node.Net.Socket as Socket
|
||||||
import Playground.Playground (Folder(..))
|
import Playground.Playground (Folder(..))
|
||||||
import Shared.Models.Body (CompileResult)
|
import Simple.JSON (writeJSON)
|
||||||
import Simple.JSON (readJSON, writeJSON)
|
|
||||||
|
|
||||||
type BuildCommand
|
type BuildCommand
|
||||||
= { command ∷ String
|
= { command ∷ String
|
||||||
@ -36,6 +28,13 @@ type BuildCommand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadCommand ∷
|
||||||
|
{ command ∷ String
|
||||||
|
}
|
||||||
|
loadCommand =
|
||||||
|
{ command: "load"
|
||||||
|
}
|
||||||
|
|
||||||
buildCommand ∷ BuildCommand
|
buildCommand ∷ BuildCommand
|
||||||
buildCommand =
|
buildCommand =
|
||||||
{ "command": "rebuild"
|
{ "command": "rebuild"
|
||||||
@ -53,18 +52,32 @@ closeSocketCanceller s =
|
|||||||
|
|
||||||
startIdeServer ∷ Folder -> Int -> Aff ChildProcess
|
startIdeServer ∷ Folder -> Int -> Aff ChildProcess
|
||||||
startIdeServer folder port = do
|
startIdeServer folder port = do
|
||||||
log
|
log $ "Spawning ide server" <> infoString
|
||||||
$ "Spawning ide server in folder "
|
cp <- spawnProcess folder "npx" [ "purs", "ide", "server", "-p", show port, "--editor-mode", "--no-watch" ]
|
||||||
<> un Folder folder
|
-- liftEffect $ onDataString (CP.stdout cp) UTF8 \str -> do
|
||||||
<> " on port "
|
-- log $ "--------" <> infoString <> "\n----------\n" <> str <> "\n----------\n"
|
||||||
<> show port
|
log $ "Spawned ide server" <> infoString
|
||||||
cp <- spawnProcess folder ("npx purs ide server -p " <> show port)
|
-- building once
|
||||||
log
|
{ error, stderr, stdout } <- execCommand folder "npx spago build"
|
||||||
$ "Spawned ide server in folder "
|
stderrStr <- liftEffect $ Buf.toString UTF8 stderr
|
||||||
<> un Folder folder
|
log $ "Built: " <> stderrStr
|
||||||
<> " on port "
|
log $ "Loading modules" <> infoString
|
||||||
<> show port
|
loadPscIde folder port
|
||||||
pure cp
|
pure cp
|
||||||
|
where
|
||||||
|
infoString =
|
||||||
|
" in folder "
|
||||||
|
<> un Folder folder
|
||||||
|
<> " on port "
|
||||||
|
<> show port
|
||||||
|
|
||||||
|
execCommand ∷ Folder -> String -> Aff CP.ExecResult
|
||||||
|
execCommand folder command =
|
||||||
|
makeAff \callback -> do
|
||||||
|
let
|
||||||
|
options = CP.defaultExecOptions { cwd = Just (un Folder folder) }
|
||||||
|
childProcess <- CP.exec command options (callback <<< Right)
|
||||||
|
pure $ effectCanceler ((log $ "Killing " <> show (CP.pid childProcess)) *> CP.kill SIGKILL childProcess)
|
||||||
|
|
||||||
restartIdeServer ∷ Folder -> Int -> Ref ChildProcess -> Aff Unit
|
restartIdeServer ∷ Folder -> Int -> Ref ChildProcess -> Aff Unit
|
||||||
restartIdeServer folder port processRef = do
|
restartIdeServer folder port processRef = do
|
||||||
@ -73,18 +86,18 @@ restartIdeServer folder port processRef = do
|
|||||||
newCp <- startIdeServer folder port
|
newCp <- startIdeServer folder port
|
||||||
Ref.write newCp processRef # liftEffect
|
Ref.write newCp processRef # liftEffect
|
||||||
|
|
||||||
spawnProcess ∷ Folder -> String -> Aff ChildProcess
|
spawnProcess ∷ Folder -> String -> Array String -> Aff ChildProcess
|
||||||
spawnProcess folder command =
|
spawnProcess folder command args =
|
||||||
makeAff \callback -> do
|
makeAff \callback -> do
|
||||||
let
|
let
|
||||||
options = CP.defaultExecOptions { cwd = Just (un Folder folder) }
|
options = CP.defaultSpawnOptions { cwd = Just (un Folder folder) }
|
||||||
childProcess <- CP.exec command options mempty
|
childProcess <- CP.spawn command args options
|
||||||
callback (Right childProcess)
|
callback (Right childProcess)
|
||||||
pure $ effectCanceler ((log $ "Killing " <> show (CP.pid childProcess)) *> CP.kill SIGKILL childProcess)
|
pure $ effectCanceler ((log $ "Killing " <> show (CP.pid childProcess)) *> CP.kill SIGKILL childProcess)
|
||||||
|
|
||||||
newtype PscIdeConnection
|
newtype PscIdeConnection
|
||||||
= PscIdeConnection
|
= PscIdeConnection
|
||||||
{ serverProcess ∷ ChildProcess
|
{ serverProcessRef ∷ Ref ChildProcess
|
||||||
, port ∷ Int
|
, port ∷ Int
|
||||||
, folder ∷ Folder
|
, folder ∷ Folder
|
||||||
}
|
}
|
||||||
@ -99,12 +112,29 @@ saveMainFile folder code = writeTextFile UTF8 (un Folder folder <> "/src/Main.pu
|
|||||||
getFolder ∷ PscIdeConnection -> Folder
|
getFolder ∷ PscIdeConnection -> Folder
|
||||||
getFolder (PscIdeConnection { folder }) = folder
|
getFolder (PscIdeConnection { folder }) = folder
|
||||||
|
|
||||||
|
loadPscIde ∷ Folder -> Int -> Aff Unit
|
||||||
|
loadPscIde folder port = do
|
||||||
|
makeAff \affCb -> do
|
||||||
|
socket <- Socket.createConnectionTCP port "localhost" mempty
|
||||||
|
-- maybe timeout?
|
||||||
|
Socket.onError socket (affCb <<< Left)
|
||||||
|
void
|
||||||
|
$ Socket.writeString socket (writeJSON loadCommand <> "\n") UTF8 (affCb (Right unit))
|
||||||
|
liftEffect
|
||||||
|
$ Socket.onClose socket case _ of
|
||||||
|
true -> mempty -- should be covered in onError
|
||||||
|
false -> do
|
||||||
|
affCb (Right unit)
|
||||||
|
let
|
||||||
|
command = writeJSON buildCommand <> "\n"
|
||||||
|
Socket.onReady socket (void $ Socket.writeString socket command UTF8 mempty)
|
||||||
|
pure (closeSocketCanceller socket)
|
||||||
|
|
||||||
compileCode ∷ String -> PscIdeConnection -> Aff String
|
compileCode ∷ String -> PscIdeConnection -> Aff String
|
||||||
compileCode code (PscIdeConnection { port, folder }) = do
|
compileCode code (PscIdeConnection { port, folder, serverProcessRef }) = do
|
||||||
|
serverProcess :: ChildProcess <- Ref.read serverProcessRef # liftEffect
|
||||||
saveMainFile folder code
|
saveMainFile folder code
|
||||||
makeAff \affCb -> do
|
makeAff \affCb -> do
|
||||||
log $
|
|
||||||
"Compiling code in " <> (un Folder folder) <> " on port " <> show port
|
|
||||||
socket <- Socket.createConnectionTCP port "localhost" mempty
|
socket <- Socket.createConnectionTCP port "localhost" mempty
|
||||||
-- maybe timeout?
|
-- maybe timeout?
|
||||||
Socket.onError socket (affCb <<< Left)
|
Socket.onError socket (affCb <<< Left)
|
||||||
@ -128,11 +158,13 @@ compileCode code (PscIdeConnection { port, folder }) = do
|
|||||||
mkConnection ∷ Folder -> Int -> Aff PscIdeConnection
|
mkConnection ∷ Folder -> Int -> Aff PscIdeConnection
|
||||||
mkConnection folder port = do
|
mkConnection folder port = do
|
||||||
serverProcess <- startIdeServer folder port
|
serverProcess <- startIdeServer folder port
|
||||||
liftEffect $ CP.onError serverProcess \e ->
|
serverProcessRef <- Ref.new serverProcess # liftEffect
|
||||||
log $ "Server process on port " <> show port <> " got error " <> show e
|
liftEffect
|
||||||
|
$ CP.onError serverProcess \e ->
|
||||||
|
log $ "Server process on port " <> show port <> " got error " <> show e
|
||||||
pure
|
pure
|
||||||
$ PscIdeConnection
|
$ PscIdeConnection
|
||||||
{ serverProcess
|
{ serverProcessRef
|
||||||
, port
|
, port
|
||||||
, folder
|
, folder
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
module Shared.Models.Body where
|
module Shared.Models.Body where
|
||||||
|
|
||||||
import Data.Maybe (Maybe(..))
|
import Data.Maybe (Maybe)
|
||||||
|
|
||||||
type CompileRequest
|
type CompileRequest
|
||||||
= { code ∷ String }
|
= { code ∷ String }
|
||||||
@ -10,27 +10,7 @@ type CompileRequest
|
|||||||
-- , resultType :: String
|
-- , resultType :: String
|
||||||
-- }
|
-- }
|
||||||
type CompileResult
|
type CompileResult
|
||||||
= { result ∷
|
= { result ∷ Array ErrorOrWarning
|
||||||
Array
|
|
||||||
{ allSpans ∷
|
|
||||||
Array
|
|
||||||
{ end ∷ Array Int
|
|
||||||
, name ∷ String
|
|
||||||
, start ∷ Array Int
|
|
||||||
}
|
|
||||||
, errorCode ∷ String
|
|
||||||
, errorLink ∷ String
|
|
||||||
, filename ∷ String
|
|
||||||
, message ∷ String
|
|
||||||
, moduleName ∷ String
|
|
||||||
, position ∷
|
|
||||||
{ endColumn ∷ Int
|
|
||||||
, endLine ∷ Int
|
|
||||||
, startColumn ∷ Int
|
|
||||||
, startLine ∷ Int
|
|
||||||
}
|
|
||||||
, suggestion ∷ Maybe Suggestion
|
|
||||||
}
|
|
||||||
, resultType ∷ String
|
, resultType ∷ String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user