11
11
import Control.Monad (forM_ )
12
12
import Control.Monad.Extra (mapMaybeM )
13
13
import Data.Either.Extra (eitherToMaybe )
14
+ import Data.Functor ((<&>) )
14
15
import Data.List (isPrefixOf , isSuffixOf , sortOn )
15
16
import Data.List.Extra (groupSort )
16
17
import qualified Data.Map.Strict as Map
@@ -19,18 +20,16 @@ import Data.Text (Text)
19
20
import qualified Data.Text as T
20
21
import qualified Data.Text.IO as T
21
22
import Lucid
22
- import Security.Advisories (AttributeOverridePolicy (NoOverrides ), OutOfBandAttributes (.. ), parseAdvisory , emptyOutOfBandAttributes )
23
- import Data.Functor ((<&>) )
24
- import Security.Advisories.Git
23
+ import Security.Advisories (AttributeOverridePolicy (NoOverrides ), OutOfBandAttributes (.. ), emptyOutOfBandAttributes , parseAdvisory )
25
24
import qualified Security.Advisories as Advisories
25
+ import Security.Advisories.Git
26
26
import System.Directory (createDirectoryIfMissing )
27
27
import System.Directory.Extra (listFilesRecursive )
28
28
import System.FilePath (takeFileName , (</>) )
29
29
30
30
{-
31
31
TODO
32
- * Generate advisories page
33
- * Select head menu
32
+ \* Select head menu
34
33
-}
35
34
36
35
-- * Actions
@@ -39,23 +38,36 @@ renderAdvisoriesIndex :: FilePath -> FilePath -> IO ()
39
38
renderAdvisoriesIndex src dst = do
40
39
let isAdvisory p =
41
40
let fileName = takeFileName p
42
- in isPrefixOf " HSEC-" fileName && isSuffixOf " .md" fileName
41
+ in isPrefixOf " HSEC-" fileName && isSuffixOf " .md" fileName
43
42
readAdvisory path = do
44
43
oob <-
45
44
getAdvisoryGitInfo path <&> \ case
46
45
Left _ -> emptyOutOfBandAttributes
47
- Right gitInfo -> emptyOutOfBandAttributes
48
- { oobPublished = Just (firstAppearanceCommitDate gitInfo)
49
- , oobModified = Just (lastModificationCommitDate gitInfo)
50
- }
46
+ Right gitInfo ->
47
+ emptyOutOfBandAttributes
48
+ { oobPublished = Just (firstAppearanceCommitDate gitInfo),
49
+ oobModified = Just (lastModificationCommitDate gitInfo)
50
+ }
51
51
fileContent <- T. readFile path
52
52
return $ eitherToMaybe $ parseAdvisory NoOverrides oob fileContent
53
53
advisoriesFileName <- filter isAdvisory <$> listFilesRecursive src
54
- advisories <- map toAdvisoryR <$> mapMaybeM readAdvisory advisoriesFileName
54
+ advisories <- mapMaybeM readAdvisory advisoriesFileName
55
+ let renderToFile' path content = do
56
+ putStrLn $ " Rendering " <> path
57
+ renderToFile path content
55
58
56
59
createDirectoryIfMissing False dst
57
- renderToFile (dst </> " by-dates.html" ) $ listByDates advisories
58
- renderToFile (dst </> " by-packages.html" ) $ listByPackages advisories
60
+ let indexAdvisories = map toAdvisoryR advisories
61
+ renderToFile' (dst </> " by-dates.html" ) $ listByDates indexAdvisories
62
+ renderToFile' (dst </> " by-packages.html" ) $ listByPackages indexAdvisories
63
+
64
+ let advisoriesDir = dst </> " advisory"
65
+ createDirectoryIfMissing False advisoriesDir
66
+ forM_ advisories $ \ advisory ->
67
+ renderToFile' (advisoriesDir </> T. unpack (advisoryHtmlFilename advisory. advisoryId)) $
68
+ inPage $
69
+ div_ [class_ " pure-u-1" ] $
70
+ toHtmlRaw advisory. advisoryHtml
59
71
return ()
60
72
61
73
-- * Rendering types
@@ -95,7 +107,7 @@ listByDates advisories =
95
107
(cycle [[] , [class_ " pure-table-odd" ]])
96
108
forM_ sortedAdvisories $ \ (advisory, trClasses) ->
97
109
tr_ trClasses $ do
98
- td_ [class_ " advisory-id" ] $ a_ [href_ " # " ] $ toHtml advisory. advisoryId
110
+ td_ [class_ " advisory-id" ] $ a_ [href_ $ advisoryLink advisory . advisoryId ] $ toHtml advisory. advisoryId
99
111
td_ [class_ " advisory-packages" ] $ toHtml $ T. intercalate " ," $ (. packageName) <$> advisory. advisoryAffected
100
112
td_ [class_ " advisory-summary" ] $ toHtml advisory. advisorySummary
101
113
@@ -130,7 +142,7 @@ listByPackages advisories =
130
142
(cycle [[] , [class_ " pure-table-odd" ]])
131
143
forM_ sortedAdvisories $ \ ((advisory, package), trClasses) ->
132
144
tr_ trClasses $ do
133
- td_ [class_ " advisory-id" ] $ a_ [href_ " # " ] $ toHtml advisory. advisoryId
145
+ td_ [class_ " advisory-id" ] $ a_ [href_ $ advisoryLink advisory . advisoryId ] $ toHtml advisory. advisoryId
134
146
td_ [class_ " advisory-introduced" ] $ toHtml package. introduced
135
147
td_ [class_ " advisory-fixed" ] $ maybe (return () ) toHtml package. fixed
136
148
td_ [class_ " advisory-summary" ] $ toHtml advisory. advisorySummary
@@ -158,6 +170,9 @@ inPage content =
158
170
" a:visited {" ,
159
171
" text-decoration: none;" ,
160
172
" color: darkblue;" ,
173
+ " }" ,
174
+ " pre {" ,
175
+ " background: lightgrey;" ,
161
176
" }"
162
177
]
163
178
body_ $ do
@@ -166,11 +181,17 @@ inPage content =
166
181
span_ [class_ " pure-menu-heading pure-menu-link" ] " Advisories list"
167
182
ul_ [class_ " pure-menu-list" ] $ do
168
183
li_ [class_ " pure-menu-item" ] $
169
- a_ [href_ " # " , class_ " pure-menu-link" ] " by date"
184
+ a_ [href_ " /by-dates.html " , class_ " pure-menu-link" ] " by date"
170
185
li_ [class_ " pure-menu-item" ] $
171
- a_ [href_ " # " , class_ " pure-menu-link" ] " by package"
186
+ a_ [href_ " /by-packages.html " , class_ " pure-menu-link" ] " by package"
172
187
div_ [class_ " content" ] content
173
188
189
+ advisoryHtmlFilename :: Text -> Text
190
+ advisoryHtmlFilename advisoryId' = advisoryId' <> " .html"
191
+
192
+ advisoryLink :: Text -> Text
193
+ advisoryLink advisoryId' = " /advisory/" <> advisoryHtmlFilename advisoryId'
194
+
174
195
toAdvisoryR :: Advisories. Advisory -> AdvisoryR
175
196
toAdvisoryR x =
176
197
AdvisoryR
0 commit comments