0 | module Text.Markdown.Lexer
 1 |
 2 | import Data.List1
 3 |
 4 | import Text.Lexer
 5 | import Text.Token
 6 |
 7 | import Text.Markdown.String
 8 | import public Text.Markdown.Tokens
 9 |
10 | %default total
11 |
12 | private
13 | markdownTokenMap : TokenMap MarkdownToken
14 | markdownTokenMap = toTokenMap $
15 |   [ (horizontalRules, MdHorizontalRules)
16 |   , (blankLine, BlankLine)
17 |   , (codeFence, MdCodeBlock)
18 |   , (pre, MdPre)
19 |   , (headingSym, HeadingSym)
20 |   , (italicsSym, ItalicsSym)
21 |   , (boldSym, BoldSym)
22 |   , (imageSym, ImageSym)
23 |   , (link, MdLink)
24 |   , (htmlCloseTag, HtmlCloseTag)
25 |   , (htmlOpenTag, HtmlOpenTag)
26 |   , (newline, MdNewLine)
27 |   , (text, MdText)
28 |   ]
29 |
30 | ||| Combine consecutive `MdText` nodes into one
31 | combineText : List MarkdownToken -> List MarkdownToken
32 | combineText [] = []
33 | combineText (el :: rest) =
34 |   let
35 |     init = (the (List1 MarkdownToken, MarkdownToken) (el ::: [], el))
36 |   in
37 |     toList $ reverse $ fst $ (foldl accumulate init rest)
38 |   where
39 |     accumulate : (List1 MarkdownToken, MarkdownToken) -> MarkdownToken -> (List1 MarkdownToken, MarkdownToken)
40 |     accumulate (acc0 ::: acc1, last) el =
41 |       case (last, el) of
42 |         (Tok MdText a, Tok MdText b) =>
43 |           let
44 |             combined = Tok MdText (a ++ b)
45 |           in
46 |           (combined ::: acc1, combined)
47 |         _ =>
48 |           (el ::: acc0 :: acc1, el)
49 |
50 | public export
51 | lexMarkdown : String -> Maybe (List MarkdownToken)
52 | lexMarkdown str
53 |   = case lex markdownTokenMap str of
54 |          (tokens, _, _, "") => Just $ combineText $ map (\tok => tok.val) tokens
55 |          _ => Nothing
56 |