Skip to content

Commit 9075b91

Browse files
authored
Render Markdown files as HTML (#2579)
1 parent 4d21a18 commit 9075b91

File tree

11 files changed

+272
-66
lines changed

11 files changed

+272
-66
lines changed

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@
66
dhall-csv/tasty/data/* binary
77
dhall-docs/tasty/data/golden/**/*.html binary
88
dhall-docs/tasty/data/package/StandaloneTextFile.txt binary
9+
dhall-docs/tasty/data/package/MarkdownFile.md binary
10+
dhall-docs/tasty/data/package/InvalidMarkdownFile.md binary
911
dhall-yaml/tasty/data/* binary

dhall-docs/dhall-docs.cabal

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@ Category: Compiler
2222
Extra-Source-Files:
2323
CHANGELOG.md
2424
README.md
25+
tasty/data/package/*.md
2526
tasty/data/package/*.txt
2627
tasty/data/package/*.dhall
2728
tasty/data/package/a/*.dhall
2829
tasty/data/package/a/b/*.dhall
2930
tasty/data/package/a/b/c/*.dhall
3031
tasty/data/package/deep/nested/folder/*.dhall
32+
tasty/data/golden/*.md.html
3133
tasty/data/golden/*.txt.html
3234
tasty/data/golden/*.dhall.html
3335
tasty/data/golden/a/*.dhall.html

dhall-docs/src/Dhall/Docs/Core.hs

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ instance MonadWriter [DocsGenWarning] GeneratedDocs where
105105

106106
data DocsGenWarning
107107
= InvalidDhall (Text.Megaparsec.ParseErrorBundle Text Void)
108-
| InvalidMarkdown MarkdownParseError
108+
| InvalidMarkdownHeader MarkdownParseError
109+
| InvalidMarkdownFile MarkdownParseError
109110
| DhallDocsCommentError (Path Rel File) CommentParseError
110111

111112
warn :: String
@@ -117,11 +118,16 @@ instance Show DocsGenWarning where
117118
Text.Megaparsec.errorBundlePretty err <>
118119
"... documentation won't be generated for this file"
119120

120-
show (InvalidMarkdown MarkdownParseError{..}) =
121+
show (InvalidMarkdownHeader MarkdownParseError{..}) =
121122
warn <>"Header comment is not markdown\n\n" <>
122123
Text.Megaparsec.errorBundlePretty unwrap <>
123124
"The original non-markdown text will be pasted in the documentation"
124125

126+
show (InvalidMarkdownFile MarkdownParseError{..}) =
127+
warn <>"Failed to parse file as markdown\n\n" <>
128+
Text.Megaparsec.errorBundlePretty unwrap <>
129+
"The original file contents will be pasted in the documentation"
130+
125131
show (DhallDocsCommentError path err) =
126132
warn <> Path.fromRelFile path <> specificError
127133
where
@@ -167,9 +173,15 @@ data FileType
167173
-- ^ Examples extracted from assertions in the file
168174
, fileComments :: FileComments
169175
}
176+
| MarkdownFile
177+
{ mmark :: MMark
178+
-- ^ Parsed Markdown from 'contents'
179+
}
170180
| TextFile
171181
deriving (Show)
172182

183+
data FileExtension = DhallExtension | MarkdownExtension | OtherExtension deriving (Show)
184+
173185
{-| Takes a list of files paths with their contents and returns the list of
174186
valid `RenderedFile`s.
175187
@@ -182,10 +194,12 @@ getAllRenderedFiles :: [(Path Rel File, ByteString)] -> GeneratedDocs [RenderedF
182194
getAllRenderedFiles =
183195
fmap Maybe.catMaybes . mapM toRenderedFile . foldr validFiles []
184196
where
185-
hasDhallExtension :: Path Rel File -> Bool
186-
hasDhallExtension absFile = case Path.splitExtension absFile of
187-
Nothing -> False
188-
Just (_, ext) -> ext == ".dhall"
197+
getFileExtension :: Path Rel File -> FileExtension
198+
getFileExtension absFile =
199+
case snd <$> Path.splitExtension absFile of
200+
Just ".dhall" -> DhallExtension
201+
Just ".md" -> MarkdownExtension
202+
_ -> OtherExtension
189203

190204
validFiles :: (Path Rel File, ByteString) -> [(Path Rel File, Text)] -> [(Path Rel File, Text)]
191205
validFiles (relFile, content) xs = case Data.Text.Encoding.decodeUtf8' content of
@@ -195,8 +209,8 @@ getAllRenderedFiles =
195209
toRenderedFile
196210
:: (Path Rel File, Text) -> GeneratedDocs (Maybe RenderedFile)
197211
toRenderedFile (relFile, contents) =
198-
case exprAndHeaderFromText (Path.fromRelFile relFile) contents of
199-
Right (Header header, expr) -> do
212+
case (exprAndHeaderFromText (Path.fromRelFile relFile) contents, getFileExtension relFile) of
213+
(Right (Header header, expr), _) -> do
200214
let denoted = denote expr :: Expr Void Import
201215

202216
headerContents <-
@@ -217,11 +231,27 @@ getAllRenderedFiles =
217231
, fileComments = FileComments headerContents
218232
}
219233
}
220-
Left ParseError{..} | hasDhallExtension relFile -> do
234+
(Left ParseError{..}, DhallExtension) -> do
221235
Writer.tell [InvalidDhall unwrap]
222236
return Nothing
223237

224-
Left _ -> do
238+
(Left ParseError{}, MarkdownExtension) ->
239+
case parseMarkdown relFile contents of
240+
Right mmark ->
241+
return $ Just $ RenderedFile
242+
{ contents
243+
, path = relFile
244+
, fileType = MarkdownFile mmark
245+
}
246+
Left err -> do
247+
Writer.tell [InvalidMarkdownFile err]
248+
return $ Just $ RenderedFile
249+
{ contents
250+
, path = relFile
251+
, fileType = TextFile
252+
}
253+
254+
_ -> do
225255
return $ Just $ RenderedFile
226256
{ contents
227257
, path = relFile
@@ -330,7 +360,7 @@ makeHtml baseImportUrl packageName characterSet RenderedFile{..} = do
330360
headerAsHtml <-
331361
case markdownToHtml path strippedHeader of
332362
Left err -> do
333-
Writer.tell [InvalidMarkdown err]
363+
Writer.tell [InvalidMarkdownHeader err]
334364
return $ Lucid.toHtml strippedHeader
335365
Right html -> return html
336366

@@ -344,6 +374,16 @@ makeHtml baseImportUrl packageName characterSet RenderedFile{..} = do
344374
DocParams{ relativeResourcesPath, packageName, characterSet, baseImportUrl }
345375

346376
return htmlAsText
377+
378+
MarkdownFile mmark -> do
379+
let htmlAsText =
380+
Text.Lazy.toStrict $ Lucid.renderText $ markdownFileToHtml
381+
path
382+
contents
383+
(render mmark)
384+
DocParams{ relativeResourcesPath, packageName, characterSet, baseImportUrl }
385+
return htmlAsText
386+
347387
TextFile -> do
348388
let htmlAsText =
349389
Text.Lazy.toStrict $ Lucid.renderText $ textFileToHtml
@@ -420,8 +460,9 @@ createIndexes baseImportUrl packageName characterSet renderedFiles = map toIndex
420460
adapt RenderedFile{..} = (stripPrefix (addHtmlExt path), m)
421461
where
422462
m = case fileType of
423-
DhallFile{..} -> mType
424-
TextFile -> Nothing
463+
DhallFile{..} -> mType
464+
MarkdownFile _ -> Nothing
465+
TextFile -> Nothing
425466

426467
html = indexToHtml
427468
indexDir

dhall-docs/src/Dhall/Docs/Html.hs

Lines changed: 60 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
module Dhall.Docs.Html
1515
( dhallFileToHtml
16+
, markdownFileToHtml
1617
, textFileToHtml
1718
, indexToHtml
1819
, DocParams(..)
@@ -47,57 +48,75 @@ data DocParams = DocParams
4748
, baseImportUrl :: Maybe Text -- ^ Base import URL
4849
}
4950

50-
-- | Generates an @`Html` ()@ with all the information about a dhall file
51-
dhallFileToHtml
52-
:: Path Rel File -- ^ Source file name, used to extract the title
53-
-> Text -- ^ Contents of the file
54-
-> Expr Src Import -- ^ AST of the file
55-
-> [Expr Void Import] -- ^ Examples extracted from the assertions of the file
56-
-> Html () -- ^ Header document as HTML
51+
-- | Generates an @`Html` ()@ containing standard elements like title,
52+
-- navbar, breadcrumbs, and the provided content.
53+
htmlTemplate
54+
:: Path Rel a -- ^ Source file name or index directory, used to extract the title
5755
-> DocParams -- ^ Parameters for the documentation
56+
-> HtmlFileType -- ^ Are we rendering an index page?
57+
-> Html () -- ^ Content to be included
5858
-> Html ()
59-
dhallFileToHtml filePath contents expr examples header params@DocParams{..} =
59+
htmlTemplate filePath params@DocParams{..} isIndex html =
6060
doctypehtml_ $ do
6161
headContents htmlTitle params
6262
body_ $ do
6363
navBar params
6464
mainContainer $ do
65-
setPageTitle params NotIndex breadcrumb
65+
setPageTitle params isIndex breadcrumb
6666
copyToClipboardButton clipboardText
6767
br_ []
68-
div_ [class_ "doc-contents"] header
69-
Control.Monad.unless (null examples) $ do
70-
h3_ "Examples"
71-
div_ [class_ "source-code code-examples"] $
72-
mapM_ (renderCodeSnippet characterSet AssertionExample) examples
73-
h3_ "Source"
74-
div_ [class_ "source-code"] $ renderCodeWithHyperLinks contents expr
68+
html
7569
where
7670
breadcrumb = relPathToBreadcrumb filePath
7771
htmlTitle = breadCrumbsToText breadcrumb
7872
clipboardText = fold baseImportUrl <> htmlTitle
7973

80-
-- | Generates an @`Html` ()@ with all the information about a non-dhall text file
74+
-- | Generates an @`Html` ()@ with all the information about a dhall file
75+
dhallFileToHtml
76+
:: Path Rel File -- ^ Source file name, used to extract the title
77+
-> Text -- ^ Contents of the file
78+
-> Expr Src Import -- ^ AST of the file
79+
-> [Expr Void Import] -- ^ Examples extracted from the assertions of the file
80+
-> Html () -- ^ Header document as HTML
81+
-> DocParams -- ^ Parameters for the documentation
82+
-> Html ()
83+
dhallFileToHtml filePath contents expr examples header params@DocParams{..} =
84+
htmlTemplate filePath params NotIndex $ do
85+
div_ [class_ "doc-contents"] header
86+
Control.Monad.unless (null examples) $ do
87+
h3_ "Examples"
88+
div_ [class_ "source-code code-examples"] $
89+
mapM_ (renderCodeSnippet characterSet AssertionExample) examples
90+
h3_ "Source"
91+
div_ [class_ "source-code"] $ renderCodeWithHyperLinks contents expr
92+
93+
-- | Generates an @`Html` ()@ with all the information about a Markdown file
94+
markdownFileToHtml
95+
:: Path Rel File -- ^ Source file name, used to extract the title
96+
-> Text -- ^ Original text contents of the file
97+
-> Html () -- ^ Contents converted to HTML
98+
-> DocParams -- ^ Parameters for the documentation
99+
-> Html ()
100+
markdownFileToHtml filePath contents html params =
101+
htmlTemplate filePath params NotIndex $ do
102+
details_ [open_ ""] $ do
103+
summary_ [class_ "part-summary"] "Rendered content"
104+
div_ [class_ "doc-contents"] html
105+
details_ $ do
106+
summary_ [class_ "part-summary"] "Source"
107+
div_ [class_ "source-code"] $ pre_ (toHtml contents)
108+
109+
110+
-- | Generates an @`Html` ()@ with all the information about a text file
81111
textFileToHtml
82112
:: Path Rel File -- ^ Source file name, used to extract the title
83113
-> Text -- ^ Contents of the file
84114
-> DocParams -- ^ Parameters for the documentation
85115
-> Html ()
86-
textFileToHtml filePath contents params@DocParams{..} =
87-
doctypehtml_ $ do
88-
headContents htmlTitle params
89-
body_ $ do
90-
navBar params
91-
mainContainer $ do
92-
setPageTitle params NotIndex breadcrumb
93-
copyToClipboardButton clipboardText
94-
br_ []
95-
h3_ "Source"
96-
div_ [class_ "source-code"] $ pre_ (toHtml contents)
97-
where
98-
breadcrumb = relPathToBreadcrumb filePath
99-
htmlTitle = breadCrumbsToText breadcrumb
100-
clipboardText = fold baseImportUrl <> htmlTitle
116+
textFileToHtml filePath contents params =
117+
htmlTemplate filePath params NotIndex $ do
118+
h3_ "Source"
119+
div_ [class_ "source-code"] $ pre_ (toHtml contents)
101120

102121
-- | Generates an index @`Html` ()@ that list all the dhall files in that folder
103122
indexToHtml
@@ -106,21 +125,15 @@ indexToHtml
106125
-> [Path Rel Dir] -- ^ Generated directories in that directory
107126
-> DocParams -- ^ Parameters for the documentation
108127
-> Html ()
109-
indexToHtml indexDir files dirs params@DocParams{..} = doctypehtml_ $ do
110-
headContents htmlTitle params
111-
body_ $ do
112-
navBar params
113-
mainContainer $ do
114-
setPageTitle params Index breadcrumbs
115-
copyToClipboardButton clipboardText
116-
br_ []
117-
Control.Monad.unless (null files) $ do
118-
h3_ "Exported files: "
119-
ul_ $ mconcat $ map listFile files
120-
121-
Control.Monad.unless (null dirs) $ do
122-
h3_ "Exported packages: "
123-
ul_ $ mconcat $ map listDir dirs
128+
indexToHtml indexDir files dirs params@DocParams{..} =
129+
htmlTemplate indexDir params Index $ do
130+
Control.Monad.unless (null files) $ do
131+
h3_ "Exported files: "
132+
ul_ $ mconcat $ map listFile files
133+
134+
Control.Monad.unless (null dirs) $ do
135+
h3_ "Exported packages: "
136+
ul_ $ mconcat $ map listDir dirs
124137

125138
where
126139
listFile :: (Path Rel File, Maybe (Expr Void Import)) -> Html ()
@@ -145,10 +158,6 @@ indexToHtml indexDir files dirs params@DocParams{..} = doctypehtml_ $ do
145158
Nothing -> file
146159
Just (f, _) -> f
147160

148-
breadcrumbs = relPathToBreadcrumb indexDir
149-
htmlTitle = breadCrumbsToText breadcrumbs
150-
clipboardText = fold baseImportUrl <> htmlTitle
151-
152161
copyToClipboardButton :: Text -> Html ()
153162
copyToClipboardButton filePath =
154163
a_ [class_ "copy-to-clipboard", data_ "path" filePath]

dhall-docs/src/Dhall/Docs/Markdown.hs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@
22
-}
33
module Dhall.Docs.Markdown
44
( MarkdownParseError(..)
5+
, MMark
6+
, parseMarkdown
57
, markdownToHtml
8+
, MMark.render
69
) where
710

811
import Data.Text (Text)
912
import Lucid
1013
import Path (File, Path, Rel)
11-
import Text.MMark (MMarkErr)
14+
import Text.MMark (MMarkErr, MMark)
1215
import Text.Megaparsec (ParseErrorBundle (..))
1316

1417
import qualified Path
@@ -27,6 +30,16 @@ markdownToHtml
2730
-> Text -- ^ Text to parse
2831
-> Either MarkdownParseError (Html ())
2932
markdownToHtml relFile contents =
33+
MMark.render <$> parseMarkdown relFile contents
34+
35+
{-| Takes a text that could contain markdown and returns either the parsed
36+
markdown or, if parsing fails, the error information.
37+
-}
38+
parseMarkdown
39+
:: Path Rel File -- ^ Used by `Mmark.parse` for error messages
40+
-> Text -- ^ Text to parse
41+
-> Either MarkdownParseError MMark
42+
parseMarkdown relFile contents =
3043
case MMark.parse (Path.fromRelFile relFile) contents of
3144
Left err -> Left MarkdownParseError { unwrap = err }
32-
Right mmark -> Right $ MMark.render mmark
45+
Right mmark -> Right mmark

dhall-docs/src/Dhall/data/assets/index.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,13 @@ h2.doc-title {
125125
margin-bottom: 0;
126126
}
127127

128+
summary.part-summary {
129+
cursor: pointer;
130+
font-size: 1.5rem;
131+
font-weight: bold;
132+
margin-top: 1rem;
133+
}
134+
128135
/******** Source code **********/
129136

130137

0 commit comments

Comments
 (0)