-
Notifications
You must be signed in to change notification settings - Fork 38
/
DependencyInjection.hs
76 lines (61 loc) · 3.87 KB
/
DependencyInjection.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
module DependencyInjection where
import CheapskateRenderer (HTML, MarkDown, htmlToText, markDownToHtml, textToMarkDown)
--import CMarkGFMRenderer (HTML, MarkDown, textToMarkDown, markDownToHtml, htmlToText)
import Control.Category ((>>>)) -- f >>> g = g . f
import qualified Data.Text as T
-- | a table of contents consists of a heading and a list of entries
data TableOfContents = Section Heading [TocEntry]
-- | a ToC entry can be a heading or a sub-table of contents
data TocEntry = Head Heading | Sub TableOfContents
-- | a heading can be just a title string or an url with a title and the actual link
data Heading = Title String | Url String String
-- | render a ToC entry as a Markdown String with the proper indentation
teToMd :: Int -> TocEntry -> String
teToMd depth (Head head) = headToMd depth head
teToMd depth (Sub toc) = tocToMd depth toc
-- | render a heading as a Markdown String with the proper indentation
headToMd :: Int -> Heading -> String
headToMd depth (Title str) = indent depth ++ "* " ++ str ++ "\n"
headToMd depth (Url title url) = indent depth ++ "* [" ++ title ++ "](" ++ url ++ ")\n"
-- | convert a ToC to Markdown String. The parameter depth is used for proper indentation.
tocToMd :: Int -> TableOfContents -> String
tocToMd depth (Section heading entries) = headToMd depth heading ++ concatMap (teToMd (depth+2)) entries
-- | produce a String of length n, consisting only of blanks
indent :: Int -> String
indent n = replicate n ' '
-- | render a ToC as a Text (consisting of properly indented Markdown)
tocToMDText :: TableOfContents -> T.Text
tocToMDText = T.pack . tocToMd 0
-- | render a ToC as a Text with html markup.
-- we specify this function as a chain of parse and rendering functions that must be provided externally
tocToHtmlText :: (TableOfContents -> T.Text) -- 1. a renderer function from ToC to Text with markdown markups
-> (T.Text -> MarkDown) -- 2. a parser function from Text to a MarkDown document
-> (MarkDown -> HTML) -- 3. a renderer function from MarkDown to an HTML document
-> (HTML -> T.Text) -- 4. a renderer function from HTML to Text
-> TableOfContents -- the actual ToC to be rendered
-> T.Text -- the Text output (containing html markup)
tocToHtmlText tocToMdText textToMd mdToHtml htmlToText =
tocToMdText >>> -- 1. render a ToC as a Text (consisting of properly indented Markdown)
textToMd >>> -- 2. parse text with Markdown to a MarkDown data structure
mdToHtml >>> -- 3. convert the MarkDown data to an HTML data structure
htmlToText -- 4. render the HTML data to a Text with hmtl markup
-- | a default implementation of a ToC to html Text renderer.
-- this function is constructed by partially applying `tocToHtmlText`
-- to four functions matching the signature of `tocToHtmlText`.
defaultTocToHtmlText :: TableOfContents -> T.Text
defaultTocToHtmlText =
tocToHtmlText
tocToMDText -- the ToC to markdown Text renderer as defined above
textToMarkDown -- a MarkDown parser, externally provided via import
markDownToHtml -- a MarkDown to HTML renderer, externally provided via import
htmlToText -- a HTML to Text with html markup, externally provided via import
demoDI = do
let toc = Section (Title "Chapter 1")
[ Sub $ Section (Title "Section a")
[Head $ Title "First Heading",
Head $ Url "Second Heading" "http://the.url"]
, Sub $ Section (Url "Section b" "http://the.section.b.url")
[ Sub $ Section (Title "UnderSection b1")
[Head $ Title "First", Head $ Title "Second"]]]
putStrLn $ T.unpack $ tocToMDText toc
putStrLn $ T.unpack $ defaultTocToHtmlText toc