Skip to content
This repository was archived by the owner on Jun 15, 2023. It is now read-only.

Commit 8923663

Browse files
committed
propagate default errors
1 parent 49aface commit 8923663

File tree

5 files changed

+173
-84
lines changed

5 files changed

+173
-84
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ sudo: required
44
node_js:
55
- 5
66
install:
7-
- npm install pulp bower -g
7+
- npm install pulp@8.2.1 bower -g
88
- npm install && bower install
99
script:
1010
- pulp test

src/Text/Markdown/SlamDown/Parser.purs

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ module Text.Markdown.SlamDown.Parser
77
import Prelude
88

99
import Data.Foldable (any, all)
10+
import Data.Either (Either)
1011
import Data.List as L
1112
import Data.Maybe as M
1213
import Data.Monoid (mempty)
@@ -18,6 +19,9 @@ import Text.Markdown.SlamDown.Syntax as SD
1819
import Text.Markdown.SlamDown.Parser.Inline as Inline
1920
import Text.Markdown.SlamDown.Parser.References as Ref
2021

22+
infixr 6 L.Cons as :
23+
24+
2125
data Container a
2226
= CText String
2327
| CBlank
@@ -310,37 +314,43 @@ parseBlocks
310314
a
311315
. (SD.Value a)
312316
L.List (Container a)
313-
L.List (SD.Block a)
317+
Either String (L.List (SD.Block a))
314318
parseBlocks cs =
315319
case cs of
316-
L.NilL.Nil
317-
L.Cons (CText s) (L.Cons (CSetextHeader n) cs) →
318-
L.Cons (SD.Header n (Inline.parseInlines $ L.singleton s)) $ parseBlocks cs
319-
L.Cons (CText s) cs →
320+
L.Nil → pure L.Nil
321+
(CText s) : (CSetextHeader n) : cs → do
322+
hd ← Inline.parseInlines $ L.singleton s
323+
tl ← parseBlocks cs
324+
pure $ (SD.Header n hd) : tl
325+
(CText s) : cs → do
320326
let
321327
sp = L.span isTextContainer cs
322-
is = Inline.parseInlines $ L.Cons s (map getCText sp.init)
323-
in
324-
L.Cons (SD.Paragraph is) $ parseBlocks sp.rest
325-
L.Cons CRule cs →
326-
L.Cons SD.Rule $ parseBlocks cs
327-
L.Cons (CATXHeader n s) cs →
328-
L.Cons (SD.Header n (Inline.parseInlines $ L.singleton s)) $ parseBlocks cs
329-
L.Cons (CBlockquote cs) cs1 →
330-
L.Cons (SD.Blockquote $ parseBlocks cs) $ parseBlocks cs1
331-
L.Cons (CListItem lt cs) cs1 →
328+
is ← Inline.parseInlines $ s : (map getCText sp.init)
329+
tl ← parseBlocks sp.rest
330+
pure $ (SD.Paragraph is) : tl
331+
CRule : cs →
332+
map (SD.Rule : _) $ parseBlocks cs
333+
(CATXHeader n s) : cs → do
334+
hd ← Inline.parseInlines $ L.singleton s
335+
tl ← parseBlocks cs
336+
pure $ (SD.Header n hd) : tl
337+
(CBlockquote cs) : cs1 → do
338+
hd ← parseBlocks cs
339+
tl ← parseBlocks cs1
340+
pure $ (SD.Blockquote hd) : tl
341+
(CListItem lt cs) : cs1 → do
332342
let
333343
sp = L.span (isListItem lt) cs1
334-
bs = parseBlocks cs
335-
bss = map (parseBlocks <<< getCListItem) sp.init
336-
in
337-
L.Cons (SD.Lst lt (L.Cons bs bss)) $ parseBlocks sp.rest
338-
L.Cons (CCodeBlockIndented ss) cs →
339-
L.Cons (SD.CodeBlock SD.Indented ss) $ parseBlocks cs
340-
L.Cons (CCodeBlockFenced eval info ss) cs →
341-
L.Cons (SD.CodeBlock (SD.Fenced eval info) ss) $ parseBlocks cs
342-
L.Cons (CLinkReference b) cs →
343-
L.Cons b $ parseBlocks cs
344+
bs parseBlocks cs
345+
bss ← traverse (parseBlocks <<< getCListItem) sp.init
346+
tl ← parseBlocks sp.rest
347+
pure $ (SD.Lst lt (bs : bss)) : tl
348+
(CCodeBlockIndented ss) : cs →
349+
map ((SD.CodeBlock SD.Indented ss) : _) $ parseBlocks cs
350+
(CCodeBlockFenced eval info ss) : cs →
351+
map ((SD.CodeBlock (SD.Fenced eval info) ss) : _) $ parseBlocks cs
352+
(CLinkReference b) : cs →
353+
map (b : _) $ parseBlocks cs
344354
L.Cons _ cs →
345355
parseBlocks cs
346356

@@ -359,8 +369,8 @@ validateSlamDown (SD.SlamDown bls) = SD.SlamDown <$> traverse validateBlock bls
359369
tabsToSpaces String String
360370
tabsToSpaces = S.replace "\t" " "
361371

362-
parseMd a. (SD.Value a) String SD.SlamDownP a
363-
parseMd s = SD.SlamDown bs
372+
parseMd a. (SD.Value a) String Either String (SD.SlamDownP a)
373+
parseMd s = map SD.SlamDown bs
364374
where
365375
lines = L.toList $ S.split "\n" $ S.replace "\r" "" $ tabsToSpaces s
366376
ctrs = parseContainers mempty lines

src/Text/Markdown/SlamDown/Parser/Inline.purs

Lines changed: 88 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ import Prelude
1010
import Control.Alt ((<|>))
1111
import Control.Apply ((<*), (*>))
1212
import Control.Lazy as Lazy
13+
import Control.Monad (when)
1314

15+
import Data.Bifunctor (lmap)
1416
import Data.Const (Const(..))
17+
import Data.Either (Either(..))
1518
import Data.Foldable (elem)
1619
import Data.Functor ((<$))
1720
import Data.Functor.Compose (Compose(..))
@@ -34,11 +37,11 @@ parseInlines
3437
a
3538
. (SD.Value a)
3639
L.List String
37-
L.List (SD.Inline a)
40+
Either String (L.List (SD.Inline a))
3841
parseInlines s =
39-
-- Note: `fromRight` is benign, because the parser never fails
40-
consolidate <<< Data.Either.Unsafe.fromRight $
41-
P.runParser (S.joinWith "\n" $ L.fromList s) inlines
42+
map consolidate
43+
$ lmap (\(P.ParseError {message}) → message)
44+
$ P.runParser (S.joinWith "\n" $ L.fromList s) inlines
4245

4346
consolidate
4447
a
@@ -142,11 +145,15 @@ inlines = L.many inline2 <* PS.eof
142145
<|> PC.try link
143146

144147
inline2 P.Parser String (SD.Inline a)
145-
inline2 =
146-
PC.try formField
147-
<|> PC.try inline1
148-
<|> PC.try image
149-
<|> other
148+
inline2 = do
149+
res ←
150+
PC.try formField
151+
<|> PC.try (Right <$> inline1)
152+
<|> PC.try (Right <$> image)
153+
<|> (Right <$> other)
154+
case res of
155+
Right v → pure v
156+
Left e → P.fail e
150157

151158
alphaNumStr P.Parser String (SD.Inline a)
152159
alphaNumStr = SD.Str <$> someOf isAlphaNum
@@ -158,7 +165,11 @@ inlines = L.many inline2 <* PS.eof
158165
(s >= "0" && s <= "9")
159166
where s = S.fromChar c
160167

161-
emphasis P.Parser String (SD.Inline a) (L.List (SD.Inline a) SD.Inline a) String P.Parser String (SD.Inline a)
168+
emphasis
169+
P.Parser String (SD.Inline a)
170+
(L.List (SD.Inline a) SD.Inline a)
171+
String
172+
P.Parser String (SD.Inline a)
162173
emphasis p f s = do
163174
PS.string s
164175
f <$> PC.manyTill p (PS.string s)
@@ -233,33 +244,63 @@ inlines = L.many inline2 <* PS.eof
233244
s ← (S.fromCharArray <<< L.fromList) <$> (PS.noneOf (S.toCharArray ";") `PC.many1Till` PS.string ";")
234245
return $ SD.Entity $ "&" <> s <> ";"
235246

236-
formField P.Parser String (SD.Inline a)
247+
formField P.Parser String (Either String (SD.Inline a))
237248
formField =
238-
SD.FormField
239-
<$> label
240-
<*> (PU.skipSpaces *> required)
241-
<*> (PU.skipSpaces *> PS.string "=" *> PU.skipSpaces *> formElement)
249+
do
250+
l ← label
251+
r ← do
252+
PU.skipSpaces
253+
required
254+
fe ← do
255+
PU.skipSpaces
256+
PS.string "="
257+
PU.skipSpaces
258+
formElement
259+
pure $ map (SD.FormField l r) fe
242260
where
243-
label = someOf isAlphaNum <|> (S.fromCharArray <<< L.fromList <$> (PS.string "[" *> PC.manyTill PS.anyChar (PS.string "]")))
261+
label =
262+
someOf isAlphaNum
263+
<|> (S.fromCharArray
264+
<<< L.fromList
265+
<$> (PS.string "[" *> PC.manyTill PS.anyChar (PS.string "]")))
266+
244267
required = PC.option false (PS.string "*" *> pure true)
245268

246-
formElement P.Parser String (SD.FormField a)
269+
formElement P.Parser String (Either String (SD.FormField a))
247270
formElement =
248271
PC.try textBox
249-
<|> PC.try radioButtons
250-
<|> PC.try checkBoxes
251-
<|> PC.try dropDown
272+
<|> PC.try (Right <$> radioButtons)
273+
<|> PC.try (Right <$> checkBoxes)
274+
<|> PC.try (Right <$> dropDown)
252275
where
253276

254-
textBox P.Parser String (SD.FormField a)
277+
textBox P.Parser String (Either String (SD.FormField a))
255278
textBox = do
256279
template ← parseTextBoxTemplate
257280
PU.skipSpaces
258-
mdef ← PC.optionMaybe $ PU.parens $ parseTextBox (\x → x /= ')') (expr id) template
259-
pure $ SD.TextBox $
260-
case mdef of
261-
M.NothingSD.transTextBox (const $ Compose M.Nothing) template
262-
M.Just def → SD.transTextBox (M.Just >>> Compose) def
281+
defVal ← PC.optionMaybe $ PS.string "("
282+
case defVal of
283+
M.Nothing → pure $ Right $ SD.TextBox $ SD.transTextBox (const $ Compose M.Nothing) template
284+
M.Just _ → do
285+
PU.skipSpaces
286+
mdef ← PC.optionMaybe $ PC.try $ parseTextBox (_ /= ')') (expr id) template
287+
case mdef of
288+
M.Just def → do
289+
PU.skipSpaces
290+
PS.string ")"
291+
pure $ Right $ SD.TextBox $ SD.transTextBox (M.Just >>> Compose) def
292+
M.Nothing
293+
pure $ Left case template of
294+
SD.DateTime _ →
295+
"Incorrect datetime default value, please use \"YYYY-MM-DD HH:mm\" or \"YYYY-MM-DDTHH:mm\" format"
296+
SD.Date _ →
297+
"Incorrect date default value, please use \"YYYY-MM-DD\" format"
298+
SD.Time _ →
299+
"Incorrect time default value, please use \"HH:mm\" or \"HH:mm:ss\" format"
300+
SD.Numeric _ →
301+
"Incorrect numeric default value"
302+
SD.PlainText _ →
303+
"Incorrect default value"
263304

264305
parseTextBoxTemplate P.Parser String (SD.TextBox (Const Unit))
265306
parseTextBoxTemplate =
@@ -372,22 +413,26 @@ parseTextBox isPlainText eta template =
372413
where
373414
parseDateTimeValue = do
374415
date ← parseDateValue
375-
PU.skipSpaces
416+
(PC.try $ void $ PS.string "T") <|> PU.skipSpaces
376417
time ← parseTimeValue
377418
pure { date, time }
378419

379420
parseDateValue = do
380-
year ← natural
421+
year ← parseYear
381422
PU.skipSpaces *> dash *> PU.skipSpaces
382423
month ← natural
424+
when (month > 12) $ P.fail "Incorrect month"
383425
PU.skipSpaces *> dash *> PU.skipSpaces
384426
day ← natural
427+
when (day > 31) $ P.fail "Incorrect day"
385428
pure { month, day, year }
386429

387430
parseTimeValue = do
388431
hours ← natural
432+
when (hours > 23) $ P.fail "Incorrect hours"
389433
PU.skipSpaces *> colon *> PU.skipSpaces
390434
minutes ← natural
435+
when (minutes > 59) $ P.fail "Incorrect minutes"
391436
PU.skipSpaces
392437
amPm ←
393438
PC.optionMaybe $
@@ -432,6 +477,21 @@ parseTextBox isPlainText eta template =
432477
digit =
433478
PS.oneOf ['0','1','2','3','4','5','6','7','8','9']
434479

480+
digitN = do
481+
ds ← digit
482+
ds
483+
# pure
484+
# S.fromCharArray
485+
# Data.Int.fromString
486+
# M.maybe (P.fail "Failed parsing digit") pure
487+
488+
parseYear = do
489+
millenia ← digitN
490+
centuries ← digitN
491+
decades ← digitN
492+
years ← digitN
493+
pure $ 1000 * millenia + 100 * centuries + 10 * decades + years
494+
435495
digits =
436496
L.some digit <#>
437497
L.fromList >>> S.fromCharArray

src/Text/Markdown/SlamDown/Pretty.purs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ prettyPrintTime { hours, minutes }=
136136
prettyPrintDateTime SD.DateTimeValue String
137137
prettyPrintDateTime { date, time } =
138138
prettyPrintDate date
139-
<> " "
139+
<> "T"
140140
<> prettyPrintTime time
141141

142142
printIntPadded Int Int String

0 commit comments

Comments
 (0)