git.iko.soy/rowtype-yoga/psfp
on master help sign in
Ja mit Faylern!
commit659e174184312c6391799e026d643533f938cf6e authorMark Eibes <mark.eibes@gmail.com> dateMon 6 Apr 2020, 00:07 (7 years ago) parentf10a067
10 files changed+94−34
blog/.psc-ide-port+1 blog/src/components/FillInTheGaps.purs+54 blog/src/components/PSLayout.purs+6−2 blog/src/components/fillInTheGaps.js+2 blog/src/pages/index.mdx+1−1 blog/src/pages/optional.mdx+17 blog/src/pages/page-2.mdx−11 components/src/Yoga/InlineCode/Component.purs+3−9 components/src/Yoga/InlineCode/Spec.purs+3−3 components/src/Yoga/InlineCode/Stories.purs+7−8
blog/.psc-ide-portnew file+1
@@ -0,0 +1 @@
1+15530
blog/src/components/FillInTheGaps.pursnew file+54
@@ -0,0 +1,54 @@
1+module FillInTheGaps where
2+
3+import Prelude
4+
5+import Data.Array as A
6+import Data.Maybe (Maybe(..), fromMaybe)
7+import Data.String (Pattern(..), split)
8+import Data.Tuple.Nested ((/\))
9+import Effect (Effect)
10+import Effect.Unsafe (unsafePerformEffect)
11+import Justifill (justifill)
12+import Partial.Unsafe (unsafeCrashWith)
13+import React.Basic (JSX, ReactComponent, element)
14+import React.Basic.DOM as R
15+import React.Basic.Hooks (ReactChildren, componentWithChildren, reactChildrenToArray, useState)
16+import React.Basic.Hooks as React
17+import Yoga.InlineCode.Component as InlineCode
18+
19+data Segment = Filler String | Hole String
20+
21+renderSegments :: ReactComponent InlineCode.Props -> ((Array (Array Segment) -> Array (Array Segment)) -> Effect Unit) -> Array (Array Segment) -> JSX
22+renderSegments ic update arrs = R.div_ (arrs `flip A.mapWithIndex` renderLine)
23+ where
24+ renderLine i l = R.div_ (l `flip A.mapWithIndex` renderSegment i)
25+ renderSegment i j = case _ of
26+ Filler s -> R.span_ [R.text s]
27+ Hole _ -> element ic $ justifill { onSubmit: \s -> update (updateSegments i j s) }
28+
29+updateSegments :: Int -> Int -> String -> Array (Array Segment) -> Array (Array Segment)
30+updateSegments i j v arrs = fromMaybe [] (A.modifyAt i (updateLine j v) arrs)
31+
32+updateLine :: Int -> String -> Array Segment -> Array Segment
33+updateLine idx v arr = fromMaybe [] (A.modifyAt idx f arr)
34+ where
35+ f = case _ of
36+ Filler s -> unsafeCrashWith "Updated a filler"
37+ Hole _ -> Hole v
38+
39+
40+fillInTheGaps :: ReactComponent { children :: ReactChildren String }
41+fillInTheGaps = unsafePerformEffect do
42+ ic <- InlineCode.makeComponent
43+ componentWithChildren "InlineCodeWithChildren" \{ children } -> React.do
44+ let
45+ separator = "???"
46+ child = children # reactChildrenToArray # A.head # fromMaybe "gurki"
47+ lines = split (Pattern "\n") child
48+ rawSegments = split (Pattern separator)
49+ toSegment = case _ of
50+ x | x == separator -> Hole ""
51+ other -> Filler other
52+ initialSegments = lines <#> \line -> rawSegments line <#> toSegment
53+ (segments :: Array (Array Segment)) /\ modifySegments <- useState initialSegments
54+ pure $ renderSegments ic (modifySegments) segments
blog/src/components/PSLayout.purs+6−2
@@ -4,9 +4,11 @@ import Prelude
44
55import Color (toHexString)
66import Data.Array as Array
7+import Data.Array.NonEmpty as NEA
78import Data.Maybe (Maybe(..), fromMaybe)
89import Data.Nullable (Nullable)
910import Data.Nullable as Nullable
11+import Data.Semigroup.Foldable (intercalateMap)
1012import Data.String as String
1113import Effect (Effect)
1214import JSS (jss, jssClasses)
@@ -20,6 +22,7 @@ import React.Basic.Hooks (ReactChildren, component, componentWithChildren, eleme
2022import React.Basic.Hooks as React
2123import Yoga.CompileEditor.Component (mkCompileEditor)
2224import Yoga.Header.Component (mkHeader)
25+import Yoga.InlineCode.Component as InlineCode
2326import Yoga.Theme (fromTheme)
2427import Yoga.Theme.CSSBaseline (mkCssBaseline)
2528import Yoga.Theme.Default (darkTheme)
@@ -87,14 +90,15 @@ mkMdxProviderComponent fetchImpl = do
8790 editor <- mkCompileEditor fetchImpl
8891 sidebar <- mkSidebar
8992 header <- mkHeader
93+ yogaInlineCode <- InlineCode.makeComponent
9094 h <- mkH
9195 p <- mkP
9296 useStyles <-
9397 makeStylesJSS
9498 $ jssClasses \(theme ∷ CSSTheme) ->
9599 { code:
96− { fontFamily: theme.codeFontFamily
97− , backgroundColor: toHexString $ theme.interfaceColour
100+ { fontFamily: theme.codeFontFamily # NEA.head
101+ , backgroundColor: theme.interfaceColour
98102 , fontSize: "10pt"
99103 , border: "1px solid #383c39"
100104 , padding: "3px"
blog/src/components/fillInTheGaps.jsnew file+2
@@ -0,0 +1,2 @@
1+const FillInTheGaps = require("./FillInTheGaps.purs").fillInTheGaps
2+export default FillInTheGaps;
blog/src/pages/index.mdx+1−1
@@ -22,5 +22,5 @@ heinz = 7
2222This is some `inline code`.
2323
2424Now go build something great.
25−<Link to="/page-2/">Go to page 2</Link>
25+<Link to="/optional/">Go to the first exercise</Link>
2626
blog/src/pages/optional.mdxnew file+17
@@ -0,0 +1,17 @@
1+import Layout from '../components/layout'
2+import SEO from '../components/seo'
3+import FillInTheGaps from '../components/fillInTheGaps'
4+
5+<SEO title="Home" keywords={['gatsby', 'application', 'react']} />
6+
7+# Optional
8+
9+<div>Udo</div>
10+<FillInTheGaps>module Main where
11+import Batteries
12+
13+main :: Effect Unit
14+main = log "???"
15+</FillInTheGaps>
16+
17+## Hans Hölzel
blog/src/pages/page-2.mdxdeleted−11
@@ -1,11 +0,0 @@
1−import { Link } from 'gatsby'
2−import Layout from '../components/layout'
3−import SEO from '../components/seo'
4−
5−<SEO title="Page two" />
6−
7−# Hi from the second page
8−
9−Welcome to page 2
10−
11−<Link to="/">Go back to the homepage</Link>
components/src/Yoga/InlineCode/Component.purs+3−9
@@ -24,12 +24,8 @@ type Props
2424type PropsR
2525 = OptionalProps (Styles.PropsR)
2626
27−data Action
28− = CompileAndRunCode String
29−
30−derive instance eqAction ∷ Eq Action
3127type OptionalProps r
32− = ( dispatch ∷ Action -> Effect Unit
28+ = ( onSubmit ∷ String -> Effect Unit
3329 , className ∷ Maybe String
3430 | r
3531 )
@@ -37,7 +33,7 @@ type OptionalProps r
3733makeComponent ∷ Effect (ReactComponent Props)
3834makeComponent = do
3935 useStyles <- makeStylesJSS styles
40− component "InlineCode" \props@{ className, dispatch } -> React.do
36+ component "InlineCode" \props@{ className, onSubmit } -> React.do
4137 value /\ modifyValue <- useState ""
4238 classes <- useStyles $ pick props
4339 pure
@@ -55,7 +51,5 @@ makeComponent = do
5551 , _data: Obj.singleton "testid" "inline-code"
5652 }
5753 ]
58− , onSubmit:
59− handler preventDefault
60− (const $ dispatch $ CompileAndRunCode value)
54+ , onSubmit: handler preventDefault (const $ onSubmit value)
6155 }
components/src/Yoga/InlineCode/Spec.purs+3−3
@@ -42,12 +42,12 @@ spec =
4242 refContent `shouldEqual` "Heinzelmän"
4343
4444data Action
45− = InlineCodeAction InlineCode.Action
45+ = InlineCodeAction String
4646
4747derive instance eqAction ∷ Eq Action
4848mkReducer ∷ Ref String -> Maybe String -> Action -> Aff (Maybe String)
4949mkReducer ref state = case _ of
50− InlineCodeAction (InlineCode.CompileAndRunCode s) -> do
50+ InlineCodeAction s -> do
5151 Ref.write s ref # liftEffect
5252 pure state
5353
@@ -60,6 +60,6 @@ mkWrapper = do
6060 pure
6161 $ element inlineCode
6262 ( justifill
63− { dispatch: dispatch <<< InlineCodeAction
63+ { onSubmit: dispatch <<< InlineCodeAction
6464 }
6565 )
components/src/Yoga/InlineCode/Stories.purs+7−8
@@ -9,7 +9,7 @@ import Data.String.CodeUnits as String
99import Data.Tuple.Nested ((/\))
1010import Effect (Effect)
1111import Effect.Aff (Aff)
12−import Effect.Class.Console (log)
12+import Effect.Console (log)
1313import Justifill (justifill)
1414import Milkis as M
1515import Milkis.Impl.Window (windowFetch)
@@ -22,7 +22,6 @@ import React.Basic.Hooks as React
2222import Storybook.Decorator.FullScreen (fullScreenDecorator)
2323import Storybook.React (Storybook, add, addDecorator, storiesOf)
2424import Yoga.CompileEditor.Component (compileAndRun)
25−import Yoga.InlineCode.Component (Action(..))
2625import Yoga.InlineCode.Component as InlineCode
2726import Yoga.Modal.Component as Modal
2827
@@ -32,7 +31,7 @@ stories = do
3231 addDecorator fullScreenDecorator
3332 add "The InlineCode" InlineCode.makeComponent
3433 [ ( justifill
35− { dispatch: \(_ ∷ InlineCode.Action) -> ((log "hi") ∷ Effect Unit)
34+ { onSubmit: log
3635 }
3736 )
3837 ]
@@ -40,7 +39,7 @@ stories = do
4039 [ { inside:
4140 \inlineCode ->
4241 [ R.text "hi!"
43− , element inlineCode (justifill { dispatch: \(_ ∷ InlineCode.Action) -> (log "Hi") ∷ Effect Unit })
42+ , element inlineCode (justifill { onSubmit: log })
4443 , R.text "hello again!"
4544 ]
4645 }
@@ -49,7 +48,7 @@ stories = do
4948 [ { inside:
5049 \inlineCode ->
5150 [ R.code_ [ R.text "main = logShow \"" ]
52− , element inlineCode (justifill { dispatch: \(_ ∷ InlineCode.Action) -> (log "Hi") ∷ Effect Unit })
51+ , element inlineCode (justifill { onSubmit: log })
5352 , R.code_ [ R.text "\"" ]
5453 ]
5554 }
@@ -84,7 +83,7 @@ type State
8483 = Maybe Boolean
8584
8685data RealAction
87− = InlineCodeAction InlineCode.Action
86+ = InlineCodeSubmitted String
8887 | CloseModal
8988
9089derive instance eqRealAction ∷ Eq RealAction
@@ -98,7 +97,7 @@ mkRealWrapper = do
9897 $ R.div_
9998 [ R.h2_ [ R.text "Let's log some 'Magick'" ]
10099 , fragment $ renderCode codePrefix
101− , element inlineCode (justifill { dispatch: dispatch <<< InlineCodeAction, width: String.length "Magick" })
100+ , element inlineCode (justifill { onSubmit: dispatch <<< InlineCodeSubmitted, width: String.length "Magick" })
102101 , fragment $ renderCode codeSuffix
103102 , R.br {}
104103 , case state of
@@ -110,7 +109,7 @@ mkRealWrapper = do
110109realReducer ∷ State -> RealAction -> Aff State
111110realReducer state = case _ of
112111 CloseModal -> pure Nothing
113− InlineCodeAction (CompileAndRunCode code) -> do
112+ InlineCodeSubmitted code -> do
114113 res <- compileAndRun (M.fetch windowFetch) { code: codePrefix <> code <> codeSuffix }
115114 (pure <<< pure) case res of
116115 Right { stdout }