@@ -6,6 +6,7 @@ module Stackage2.ServerBundle
6 ( serverBundle
6 ( serverBundle
7 , epochTime
7 , epochTime
8 , bpAllPackages
8 , bpAllPackages
11import qualified Codec.Archive.Tar as Tar
12import qualified Codec.Archive.Tar as Tar
@@ -17,6 +18,9 @@ import Stackage2.BuildConstraints
17import Stackage2.BuildPlan
18import Stackage2.BuildPlan
18import Stackage2.Prelude
19import Stackage2.Prelude
19import qualified System.PosixCompat.Time as PC
20import qualified System.PosixCompat.Time as PC
21+import qualified Text.XML as X
22+import Text.XML.Cursor
23+import Filesystem (isFile)
21-- | Get current time
25-- | Get current time
22epochTime :: IO Tar.EpochTime
26epochTime :: IO Tar.EpochTime
@@ -61,3 +65,43 @@ serverBundle time title slug bp@BuildPlan {..} = GZip.compress $ Tar.write
61 toBuilder (asText "-") ++
65 toBuilder (asText "-") ++
62 toBuilder (display version) ++
66 toBuilder (display version) ++
63 toBuilder (asText "\n")
67 toBuilder (asText "\n")
69+docsListing :: BuildPlan
70+ -> FilePath -- ^ docs directory
72+docsListing bp docsDir =
73+ fmap (Y.encode . fold) $ mapM go $ mapToList $ bpAllPackages bp
75+ go :: (PackageName, Version) -> IO (Map Text Y.Value)
76+ go (package, version) = do -- handleAny (const $ return mempty) $ do
77+ let dirname = fpFromText (concat
82+ indexFP = (docsDir </> dirname </> "index.html")
86+ doc <- flip X.readFile indexFP X.def
87+ { X.psDecodeEntities = X.decodeHtmlEntities
89+ let cursor = fromDocument doc
90+ getPair x = take 1 $ do
91+ href <- attribute "href" x
92+ let name = concat $ x $// content
93+ guard $ not $ null name
95+ pairs = cursor $// attributeIs "class" "module"
96+ &/ laxElement "a" >=> getPair
97+ m <- fmap fold $ forM pairs $ \(href, name) -> do
98+ let suffix = dirname </> fpFromText href
99+ e <- isFile $ docsDir </> suffix
101+ then asMap $ singletonMap name [fpToText dirname, href]
103+ return $ singletonMap (display package) $ Y.object
104+ [ "version" Y..= display version