git.iko.soy/rowtype-yoga/psfp
on master help sign in
Simplified Fill In The Gaps
d37fadcMark Eibes
blog/.psc-ide-portnew file+1
@@ -0,0 +1 @@
1+15613
blog/src/components/PSLayout.purs+27−8
@@ -1,14 +1,17 @@
1module PSLayout where
1module PSLayout where
2
2
3import Prelude
3import Prelude
4+
5+import Data.Array as A
4import Data.Array as Array
6import Data.Array as Array
5import Data.Array.NonEmpty as NEA
7import Data.Array.NonEmpty as NEA
6import Data.Maybe (Maybe(..), fromMaybe)
8import Data.Maybe (Maybe(..), fromMaybe)
7import Data.Nullable (Nullable)
9import Data.Nullable (Nullable)
8import Data.Nullable as Nullable
10import Data.Nullable as Nullable
9import Data.String as String
11import Data.String as String
12+import Data.Tuple.Nested ((/\))
13+import Debug.Trace (spy)
10import Effect (Effect)
14import Effect (Effect)
11−import Effect.Unsafe (unsafePerformEffect)
12import JSS (jss, jssClasses)
15import JSS (jss, jssClasses)
13import Justifill (justifill)
16import Justifill (justifill)
14import Milkis.Impl (FetchImpl)
17import Milkis.Impl (FetchImpl)
@@ -16,13 +19,15 @@ import React.Basic (JSX, ReactComponent)
16import React.Basic.DOM (unsafeCreateDOMComponent)
19import React.Basic.DOM (unsafeCreateDOMComponent)
17import React.Basic.DOM as R
20import React.Basic.DOM as R
18import React.Basic.Helpers (jsx)
21import React.Basic.Helpers (jsx)
19−import React.Basic.Hooks (ReactChildren, component, componentWithChildren, element, reactChildrenToArray, useState)
22+import React.Basic.Hooks (ReactChildren, component, componentWithChildren, element, reactChildrenToArray, useEffect, useState)
20import React.Basic.Hooks as React
23import React.Basic.Hooks as React
24+import Unsafe.Coerce (unsafeCoerce)
21import Yoga.Box.Component as Box
25import Yoga.Box.Component as Box
22import Yoga.CompileEditor.Component (mkCompileEditor)
26import Yoga.CompileEditor.Component (mkCompileEditor)
23import Yoga.Compiler.Api (apiCompiler)
27import Yoga.Compiler.Api (apiCompiler)
24import Yoga.FillInTheGaps.Component as FillInTheGaps
28import Yoga.FillInTheGaps.Component as FillInTheGaps
25import Yoga.Header.Component (mkHeader)
29import Yoga.Header.Component (mkHeader)
30+import Yoga.Helpers ((?||))
26import Yoga.InlineCode.Component as InlineCode
31import Yoga.InlineCode.Component as InlineCode
27import Yoga.Theme (fromTheme)
32import Yoga.Theme (fromTheme)
28import Yoga.Theme.CSSBaseline (mkCssBaseline)
33import Yoga.Theme.CSSBaseline (mkCssBaseline)
@@ -78,9 +83,12 @@ mkLayout fetchImpl = do
78 ]
83 ]
79 }
84 }
80
85
81−mkSecret :: Effect ( ReactComponent { kids ∷ Array JSX , visible ∷ Boolean })
86+mkSecret :: Effect ( ReactComponent { kids ∷ Array JSX , visible ∷ Boolean, register :: Effect Unit })
82mkSecret = do
87mkSecret = do
83− component "Secret" \{ kids, visible } -> React.do
88+ component "Secret" \{ kids, visible, register } -> React.do
89+ useEffect visible do
90+ unless visible register
91+ pure mempty
84 pure
92 pure
85 $ R.div
93 $ R.div
86 { style: R.css { visibility: if visible then "visible" else "hidden" }
94 { style: R.css { visibility: if visible then "visible" else "hidden" }
@@ -124,16 +132,20 @@ mkMdxProviderComponent fetchImpl = do
124 }
132 }
125 componentWithChildren "MDXProviderComponent" \{ children, siteInfo } -> React.do
133 componentWithChildren "MDXProviderComponent" \{ children, siteInfo } -> React.do
126 classes <- useStyles {}
134 classes <- useStyles {}
127− sections <- useState []
135+ visibleThroughKey /\ updateVisible <- useState ""
128 let
136 let
129 baseline child = element cssBaseline { kids: child }
137 baseline child = element cssBaseline { kids: child }
138+ kids = reactChildrenToArray children
139+ visibleKids = spy "visibleKids" $ fromMaybe kids do
140+ i <- kids # A.findIndex (\x -> (unsafeCoerce x).key == visibleThroughKey)
141+ pure $ A.take (i+1) kids
130
142
131 siteInfoJSX =
143 siteInfoJSX =
132 R.div
144 R.div
133 { children:
145 { children:
134 [ jsx header { className: "" } [ R.text siteInfo.site.siteMetadata.title ]
146 [ jsx header { className: "" } [ R.text siteInfo.site.siteMetadata.title ]
135 , element sidebar { links: siteInfo.site.siteMetadata.menuLinks }
147 , element sidebar { links: siteInfo.site.siteMetadata.menuLinks }
136− , jsx box {} (reactChildrenToArray children)
148+ , jsx box {} visibleKids
137 ]
149 ]
138 }
150 }
139
151
@@ -152,8 +164,8 @@ mkMdxProviderComponent fetchImpl = do
152 R.div
164 R.div
153 { children: [ element p { text: props.children } ]
165 { children: [ element p { text: props.children } ]
154 }
166 }
155− , thematicBreak:
167+ -- , thematicBreak:
156− \props -> R.div_ [ R.text "HOUI" ]
168+ -- \props -> jsx secret { register: updateSections (Map.insert ) }
157 , inlineCode:
169 , inlineCode:
158 \props -> do
170 \props -> do
159 R.span { className: classes.code, children: props.children }
171 R.span { className: classes.code, children: props.children }
@@ -194,6 +206,13 @@ mkMdxProviderComponent fetchImpl = do
194 }
206 }
195 false, _ -> element (unsafeCreateDOMComponent "pre") props
207 false, _ -> element (unsafeCreateDOMComponent "pre") props
196 }
208 }
209+
210+ useEffect (A.length kids) do
211+ let
212+ firstGaps = kids # A.find (\x -> (unsafeCoerce x).props.mdxType == "pre" && ((unsafeCoerce x).props.children.props.className == "language-puregaps")) <#> (\x -> (unsafeCoerce x).key)
213+ lastKey = kids # A.last # unsafeCoerce # _.key
214+ updateVisible (const (firstGaps ?|| lastKey))
215+ pure mempty
197 pure
216 pure
198 $ baseline
217 $ baseline
199 [ element mdxProvider
218 [ element mdxProvider
blog/src/pages/optional.mdx+13−1
@@ -6,7 +6,7 @@ import SEO from '../components/seo'
6# Optional
6# Optional
7
7
8```puregaps
8```puregaps
9−--result Apero
9+--result Hello World
10module Main where
10module Main where
11import Grimoire
11import Grimoire
12
12
@@ -19,4 +19,16 @@ incantation = cast $
19
19
20---
20---
21
21
22+```puregaps
23+--result Hello World
24+module Main where
25+import Grimoire
26+
27+incantation :: Effect Unit
28+--start here
29+incantation = cast $
30+ "{-Hello World-}"
31+--end here
32+```
33+
22## Hans Hölzel
34## Hans Hölzel
components/src/Yoga/FillInTheGaps/Component.purs+13−209
@@ -1,83 +1,24 @@
1module Yoga.FillInTheGaps.Component where
1module Yoga.FillInTheGaps.Component where
2
2
3import Prelude
3import Prelude
4−import Data.Array (foldMap, foldr, intercalate)
5import Data.Array as A
4import Data.Array as A
6−import Data.Either (Either(..))
7−import Data.Foldable (foldl)
8−import Data.Function.Uncurried (mkFn2)
9−import Data.Lens ((%~))
10−import Data.Lens.Index (ix)
11−import Data.Maybe (Maybe(..), fromMaybe', isJust, isNothing)
12−import Data.Monoid (guard)
13−import Data.String (Pattern(..), split)
14−import Data.String as S
15−import Data.String.Regex (Regex)
16−import Data.String.Regex as Regex
17−import Data.String.Regex.Flags as RegexFlags
18−import Data.String.Regex.Unsafe (unsafeRegex)
19import Data.Tuple.Nested ((/\))
5import Data.Tuple.Nested ((/\))
20−import Debug.Trace (spy)
21import Effect (Effect)
6import Effect (Effect)
22−import Effect.Aff (launchAff_)
7+import Effect.Aff (Milliseconds(..), delay)
23import Effect.Class (liftEffect)
8import Effect.Class (liftEffect)
24import Justifill (justifill)
9import Justifill (justifill)
25−import Partial.Unsafe (unsafeCrashWith)
26−import React.Basic (JSX, ReactComponent, element, fragment)
10+import React.Basic (JSX, ReactComponent, element)
27−import React.Basic.DOM (css)
28import React.Basic.DOM as R
11import React.Basic.DOM as R
29−import React.Basic.Events (handler_)
30−import React.Basic.Helpers (jsx)
31import React.Basic.Hooks (component, useState)
12import React.Basic.Hooks (component, useState)
32import React.Basic.Hooks as React
13import React.Basic.Hooks as React
33−import React.Basic.Hooks.Spring (useTransition)
14+import React.Basic.Hooks.Aff (useAff)
34import React.Basic.SyntaxHighlighter.Component (HighlighterTheme, syntaxHighlighterImpl)
15import React.Basic.SyntaxHighlighter.Component (HighlighterTheme, syntaxHighlighterImpl)
35−import Shared.Models.Body (CompileResult, RunResult)
16+import Yoga.FillInTheGaps.Logic (Segment(..), updateSegments)
36−import Yoga.Button.Component (ButtonType(..), mkButton)
37−import Yoga.ClickAway.Component as ClickAway
38−import Yoga.CloseIcon.Component as CloseIcon
39−import Yoga.Cluster.Component as Cluster
40−import Yoga.Compiler.Types (Compiler)
41import Yoga.Helpers ((?||))
17import Yoga.Helpers ((?||))
42import Yoga.InlineCode.Component as InlineCode
18import Yoga.InlineCode.Component as InlineCode
43−import Yoga.Modal.Component as Modal
44import Yoga.Theme.Styles (useTheme)
19import Yoga.Theme.Styles (useTheme)
45import Yoga.Theme.Syntax (mkHighlighterTheme)
20import Yoga.Theme.Syntax (mkHighlighterTheme)
46
21
47−data Segment
48− = ExpectedResult String
49− | Start
50− | End
51− | Filler String
52− | Hole Int String
53−
54−derive instance eqSegment ∷ Eq Segment
55−getResult ∷ Segment -> Maybe String
56−getResult = case _ of
57− ExpectedResult r -> Just r
58− _ -> Nothing
59−
60−findResult ∷ Array Segment -> String
61−findResult = fromMaybe' (\_ -> unsafeCrashWith "Even teachers make mistakes") <<< A.findMap getResult
62−
63−toCode ∷ Array (Array Segment) -> String
64−toCode lines = intercalate "\n" mapped
65− where
66− mapped = lines <#> (intercalate "" <<< map segmentToCode)
67− segmentToCode = case _ of
68− Filler s -> s
69− Hole _ s -> s
70− _ -> ""
71−
72−complete ∷ Array (Array Segment) -> Boolean
73−complete arr = foldl f true (join arr)
74− where
75− f acc seg =
76− acc
77− && case seg of
78− Hole _ s -> s /= ""
79− _ -> true
80−
81visibleRange ∷ Array (Array Segment) -> { end ∷ Int, start ∷ Int }
22visibleRange ∷ Array (Array Segment) -> { end ∷ Int, start ∷ Int }
82visibleRange arr = { start, end }
23visibleRange arr = { start, end }
83 where
24 where
@@ -91,7 +32,7 @@ renderSegments highlighterTheme ic update arrs = R.div_ (A.mapWithIndex renderLi
91 renderLine i l = R.div_ (A.mapWithIndex (renderSegment i) l)
32 renderLine i l = R.div_ (A.mapWithIndex (renderSegment i) l)
92 renderSegment i j s =
33 renderSegment i j s =
93 if between start end i then case s of
34 if between start end i then case s of
94− Filler s' -> element syntaxHighlighterImpl { style: highlighterTheme, language: "purescript", children: spy "ch" s' }
35+ Filler s' -> element syntaxHighlighterImpl { style: highlighterTheme, language: "purescript", children: s' }
95 Hole width _ ->
36 Hole width _ ->
96 element ic
37 element ic
97 $ justifill
38 $ justifill
@@ -102,150 +43,13 @@ renderSegments highlighterTheme ic update arrs = R.div_ (A.mapWithIndex renderLi
102 else
43 else
103 mempty
44 mempty
104
45
105−updateSegments ∷ Int -> Int -> String -> Array (Array Segment) -> Array (Array Segment)
106−updateSegments i j v = (ix i <<< ix j) %~ f
107− where
108− f = case _ of
109− Hole h _ -> Hole h v
110− _ -> unsafeCrashWith "Updated a non-hole"
111−
112−holeRegex ∷ Regex
113−holeRegex = unsafeRegex "({-.*?-})" RegexFlags.global
114−
115−resultRegex ∷ Regex
116−resultRegex = unsafeRegex "--result" RegexFlags.global
117−
118−startRegex ∷ Regex
119−startRegex = unsafeRegex "--start here" RegexFlags.global
120−
121−endRegex ∷ Regex
122−endRegex = unsafeRegex "--end here" RegexFlags.global
123−
124−rawSegments ∷ String -> Array String
125−rawSegments = Regex.split holeRegex
126−
127−toSegment ∷ String -> Segment
128−toSegment = case _ of
129− x
130− | Regex.test holeRegex x -> Hole (S.length x - 4) ""
131− x
132− | S.indexOf (Pattern "--result ") x == Just 0 -> ExpectedResult ((S.stripPrefix (Pattern "--result ") x) ?|| "")
133− x
134− | Regex.test startRegex x -> Start
135− x
136− | Regex.test endRegex x -> End
137− other -> Filler other
138−
139−-- Glues together Filler segments
140−-- [[Filler "line1"], [Filler "line2"]] --> [[Filler "line1\nline2"]]
141−-- [[Filler "line1", Filler "line2"]] --> [[Filler "line1\nline2"]]
142−-- [[Filler "line1", Filler "line2"], [Filler "line3"]] --> [[Filler "line1\nline2\line3"]]
143−smooshFillers ∷ Array (Array Segment) -> Array (Array Segment)
144−smooshFillers = foldl smooshOuter []
145− where
146− smooshInner segments segment = case segment, A.unsnoc segments of
147− Filler f, Just { init, last: Filler prev } -> A.snoc init (Filler (prev <> "\n" <> f))
148− _, _ -> A.snoc segments segment
149− smooshOuter acc segs = case foldl smooshInner [] segs, A.unsnoc acc of
150− [ Filler f ], Just { init, last: [ Filler prev ] } -> A.snoc init [ Filler (prev <> "\n" <> f) ]
151− _, _ -> A.snoc acc segs
152−
153−type Ctx r
154− = (Compiler r)
155−
156−makeComponent ∷ { | Ctx () } -> Effect (ReactComponent { code ∷ String })
46+makeComponent ∷ Effect (ReactComponent { initialSegments ∷ Array (Array Segment), update ∷ Array (Array Segment) -> Effect Unit })
157−makeComponent { compileAndRun } = do
47+makeComponent = do
158 ic <- InlineCode.makeComponent
48 ic <- InlineCode.makeComponent
159− modal <- Modal.makeComponent
160− closeIcon <- CloseIcon.makeComponent
161− cluster <- Cluster.makeComponent
162− clickAway <- ClickAway.makeComponent
163− button <- mkButton
164− component "FillInTheGaps" \{ code } -> React.do
49+ component "FillInTheGaps" \{ initialSegments, update } -> React.do
165− let
166− lines = split (Pattern "\n") code
167−
168− initialSegments = smooshFillers (lines <#> \line -> rawSegments line <#> toSegment)
169 segments /\ modifySegments <- useState initialSegments
50 segments /\ modifySegments <- useState initialSegments
170− result /\ modifyResult <- useState Nothing
51+ useAff segments do
171− cssTheme <- useTheme
52+ delay (200.0 # Milliseconds)
172− let
53+ update segments # liftEffect
173− highlighterTheme = mkHighlighterTheme cssTheme
54+ highlighterTheme <- useTheme <#> mkHighlighterTheme
174− modalTransitions <-
175− useTransition [ result ] (Just show)
176− $ css
177− { from: { opacity: 0.0, transform: "translate3d(-50%, -50%, 0) scale3d(0.3, 0.3, 1.0)" }
178− , enter: { opacity: 1.0, transform: "translate3d(-50%, -50%, 0) scale3d(1.0, 1.0, 1.0)" }
179− , leave: { opacity: 0.0, transform: "translate3d(-50%, -50%, 0) scale3d(0.3, 0.3, 1.0)" }
180− , config:
181− mkFn2 \_ state -> case state of
182− "leave" -> { mass: 1.0, tension: 140, friction: 15 }
183− _ -> { mass: 1.0, tension: 170, friction: 20 }
184− }
185− clickAwayTransitions <-
186− useTransition [ result ] (Just show)
187− $ css
188− { from: { opacity: 0.0 }
189− , enter: { opacity: 1.0 }
190− , leave: { opacity: 0.0 }
191− , config:
192− mkFn2 \_ state -> case state of
193− "leave" -> { mass: 1.0, tension: 140, friction: 15 }
194− _ -> { mass: 1.0, tension: 170, friction: 20 }
195− }
196− let
197− expectedResult = findResult (join segments)
198−
199− onClick =
200− launchAff_ do
201− do
202− res <- compileAndRun { code: toCode segments }
203− modifyResult (const (Just $ res)) # liftEffect
204− pure
205− $ fragment
206− $ [ renderSegments highlighterTheme ic (modifySegments) segments
55+ pure $ renderSegments highlighterTheme ic (modifySegments) segments
207− , jsx cluster {}
208− [ R.div_
209− [ jsx button
210− { onClick: handler_ onClick
211− , buttonType:
212− if complete segments && isNothing result then
213− HighlightedButton
214− else
215− DisabledButton
216− }
217− [ R.text "Incantate" ]
218− ]
219− ]
220− , fragment
221− $ clickAwayTransitions
222− >>= \{ item, key, props } ->
223− guard (isJust item)
224− $ join item
225− # foldMap \_ ->
226− [ element clickAway (justifill { allowEscape: true, style: props, onClick: modifyResult (const Nothing) }) ]
227− , fragment
228− $ modalTransitions
229− >>= \{ item, key, props } ->
230− guard (isJust item)
231− $ join item
232− # foldMap \r ->
233− [ jsx modal
234− { title:
235− case r of
236− (Right { stdout })
237− | S.stripSuffix (S.Pattern "\n") stdout == Just expectedResult -> "Hooray!"
238− (Left l) -> "Does not compile"
239− (Right _) -> "Not " <> (findResult $ join segments)
240− , icon: element closeIcon { onClick: modifyResult (const Nothing), style: Nothing }
241− , style: props
242− }
243− [ R.pre_ [ R.text $ compileResultToString result ] ]
244− ]
245− ]
246−
247−compileResultToString ∷ Maybe (Either CompileResult RunResult) -> String
248−compileResultToString = case _ of
249− Nothing -> ""
250− Just (Left cr) -> cr.result <#> _.message # intercalate "\n"
251− Just (Right r) -> r.stdout
components/src/Yoga/FillInTheGaps/Logic.pursnew file+118
@@ -0,0 +1,118 @@
1+module Yoga.FillInTheGaps.Logic where
2+
3+import Prelude
4+import Data.Array (intercalate)
5+import Data.Array as A
6+import Data.Either (Either(..))
7+import Data.Foldable (foldl)
8+import Data.Lens ((%~))
9+import Data.Lens.Index (ix)
10+import Data.Maybe (Maybe(..), fromMaybe')
11+import Data.String (Pattern(..), split)
12+import Data.String as S
13+import Data.String.Regex (Regex)
14+import Data.String.Regex as Regex
15+import Data.String.Regex.Flags as RegexFlags
16+import Data.String.Regex.Unsafe (unsafeRegex)
17+import Data.Tuple.Nested ((/\))
18+import Debug.Trace (spy)
19+import Effect (Effect)
20+import Justifill (justifill)
21+import Partial.Unsafe (unsafeCrashWith)
22+import React.Basic (JSX, ReactComponent, element)
23+import React.Basic.DOM as R
24+import React.Basic.Hooks (component, useState)
25+import React.Basic.Hooks as React
26+import React.Basic.SyntaxHighlighter.Component (HighlighterTheme, syntaxHighlighterImpl)
27+import Shared.Models.Body (CompileResult, RunResult)
28+import Yoga.Helpers ((?||))
29+import Yoga.InlineCode.Component as InlineCode
30+import Yoga.Theme.Styles (useTheme)
31+import Yoga.Theme.Syntax (mkHighlighterTheme)
32+
33+complete ∷ Array (Array Segment) -> Boolean
34+complete arr = foldl f true (join arr)
35+ where
36+ f acc seg =
37+ acc
38+ && case seg of
39+ Hole _ s -> s /= ""
40+ _ -> true
41+
42+data Segment
43+ = ExpectedResult String
44+ | Start
45+ | End
46+ | Filler String
47+ | Hole Int String
48+
49+derive instance eqSegment ∷ Eq Segment
50+getResult ∷ Segment -> Maybe String
51+getResult = case _ of
52+ ExpectedResult r -> Just r
53+ _ -> Nothing
54+
55+findResult ∷ Array Segment -> String
56+findResult = fromMaybe' (\_ -> unsafeCrashWith "Even teachers make mistakes") <<< A.findMap getResult
57+
58+toCode ∷ Array (Array Segment) -> String
59+toCode lines = intercalate "\n" mapped
60+ where
61+ mapped = lines <#> (intercalate "" <<< map segmentToCode)
62+ segmentToCode = case _ of
63+ Filler s -> s
64+ Hole _ s -> s
65+ _ -> ""
66+
67+holeRegex ∷ Regex
68+holeRegex = unsafeRegex "({-.*?-})" RegexFlags.global
69+
70+resultRegex ∷ Regex
71+resultRegex = unsafeRegex "--result" RegexFlags.global
72+
73+startRegex ∷ Regex
74+startRegex = unsafeRegex "--start here" RegexFlags.global
75+
76+endRegex ∷ Regex
77+endRegex = unsafeRegex "--end here" RegexFlags.global
78+
79+rawSegments ∷ String -> Array String
80+rawSegments = Regex.split holeRegex
81+
82+toSegment ∷ String -> Segment
83+toSegment = case _ of
84+ x
85+ | Regex.test holeRegex x -> Hole (S.length x - 4) ""
86+ x
87+ | S.indexOf (Pattern "--result ") x == Just 0 -> ExpectedResult ((S.stripPrefix (Pattern "--result ") x) ?|| "")
88+ x
89+ | Regex.test startRegex x -> Start
90+ x
91+ | Regex.test endRegex x -> End
92+ other -> Filler other
93+
94+updateSegments ∷ Int -> Int -> String -> Array (Array Segment) -> Array (Array Segment)
95+updateSegments i j v = (ix i <<< ix j) %~ f
96+ where
97+ f = case _ of
98+ Hole h _ -> Hole h v
99+ _ -> unsafeCrashWith "Updated a non-hole"
100+
101+-- Glues together Filler segments
102+-- [[Filler "line1"], [Filler "line2"]] --> [[Filler "line1\nline2"]]
103+-- [[Filler "line1", Filler "line2"]] --> [[Filler "line1\nline2"]]
104+-- [[Filler "line1", Filler "line2"], [Filler "line3"]] --> [[Filler "line1\nline2\line3"]]
105+smooshFillers ∷ Array (Array Segment) -> Array (Array Segment)
106+smooshFillers = foldl smooshOuter []
107+ where
108+ smooshInner segments segment = case segment, A.unsnoc segments of
109+ Filler f, Just { init, last: Filler prev } -> A.snoc init (Filler (prev <> "\n" <> f))
110+ _, _ -> A.snoc segments segment
111+ smooshOuter acc segs = case foldl smooshInner [] segs, A.unsnoc acc of
112+ [ Filler f ], Just { init, last: [ Filler prev ] } -> A.snoc init [ Filler (prev <> "\n" <> f) ]
113+ _, _ -> A.snoc acc segs
114+
115+parseSegments code = segments
116+ where
117+ lines = split (Pattern "\n") code
118+ segments = smooshFillers (lines <#> \line -> rawSegments line <#> toSegment)
components/src/Yoga/FillInTheGaps/Stories.purs+5−16
@@ -1,30 +1,19 @@
1module Yoga.FillInTheGaps.Stories where
1module Yoga.FillInTheGaps.Stories where
2
2
3import Prelude hiding (add)
3import Prelude hiding (add)
4−import Data.Either (Either(..))
5−import Data.Maybe (Maybe(..))
6import Data.String as String
4import Data.String as String
7import Effect (Effect)
5import Effect (Effect)
8import Storybook.Decorator.FullScreen (fullScreenDecorator)
6import Storybook.Decorator.FullScreen (fullScreenDecorator)
9import Storybook.React (Storybook, add, addDecorator, storiesOf)
7import Storybook.React (Storybook, add, addDecorator, storiesOf)
10import Yoga.FillInTheGaps.Component as FillInTheGaps
8import Yoga.FillInTheGaps.Component as FillInTheGaps
11−
12−ctx ∷ { | FillInTheGaps.Ctx () }
9+import Yoga.FillInTheGaps.Logic (parseSegments)
13−ctx =
14− { compileAndRun
15− }
16− where
17− compileAndRun = case _ of
18− { code }
19− | code == correctCode -> pure (Right { code: Nothing, stdout: "Hello World\n", stderr: "" })
20− other -> pure (Right { code: Nothing, stdout: "Not hello world", stderr: "" })
21
10
22stories ∷ Effect Storybook
11stories ∷ Effect Storybook
23stories = do
12stories = do
24 storiesOf "FillInTheGaps" do
13 storiesOf "FillInTheGaps" do
25 addDecorator fullScreenDecorator
14 addDecorator fullScreenDecorator
26− add "The FillInTheGaps" (FillInTheGaps.makeComponent ctx)
15+ add "The FillInTheGaps" (FillInTheGaps.makeComponent)
27− [ { code: codeWithHoles }
16+ [ { initialSegments: parseSegments codeWithHoles, update: pure (pure unit) }
28 ]
17 ]
29
18
30codeWithHoles =
19codeWithHoles =
@@ -33,9 +22,9 @@ codeWithHoles =
33module Main where
22module Main where
34import Grimoire
23import Grimoire
35
24
36−main :: Effect Unit
25+incantation :: Effect Unit
37--start here
26--start here
38−main = cast
27+incantation = cast
39 "{-Hello World-}"
28 "{-Hello World-}"
40--end here
29--end here
41"""
30"""