summaryrefslogtreecommitdiff
path: root/build/generate-rss.hs
diff options
context:
space:
mode:
Diffstat (limited to 'build/generate-rss.hs')
-rwxr-xr-xbuild/generate-rss.hs82
1 files changed, 82 insertions, 0 deletions
diff --git a/build/generate-rss.hs b/build/generate-rss.hs
new file mode 100755
index 0000000..18d2d6f
--- /dev/null
+++ b/build/generate-rss.hs
@@ -0,0 +1,82 @@
1#!/usr/bin/env runhaskell
2
3import System.Environment (getArgs)
4import qualified Control.Monad.State as S
5import Control.Monad (sequence)
6
7import Text.Feed.Constructor
8import Text.Feed.Util
9import Text.Feed.Export
10import Text.Feed.Types
11
12import Text.Pandoc
13import Text.Pandoc.Pretty
14
15import qualified System.Time as T
16import qualified System.Posix.Files as F
17import qualified Text.XML.Light.Output as X
18import qualified System.FilePath as FP
19import System.Posix.Types
20
21import Data.Maybe (fromMaybe)
22import Data.List (dropWhileEnd, isSuffixOf)
23
24type FeedState = (Feed, Maybe T.ClockTime)
25
26feedKind = RSSKind $ Just "test" -- DEBUG
27
28extract_title :: Pandoc -> String
29extract_title d@(Pandoc m _) = do
30 title <- render Nothing $ cat $ map pretty (docTitle m)
31 return title
32 where pretty :: Inline -> Doc
33 pretty (Str s) = text s
34 pretty Space = space
35 pretty _ = empty
36
37main :: IO ()
38main = do
39 (title:entries) <- getArgs
40 currentTime <- T.getClockTime
41 let feed = withFeedHome "http://dirty-haskell.org" $ withFeedTitle title $ newFeed feedKind
42 (populatedFeed, itemTime) <- S.execStateT (sequence $ map addItem' entries) (feed, Nothing)
43 let populatedFeed' = withFeedDate (toFeedDateString feedKind $ fromMaybe currentTime itemTime) populatedFeed
44 putStrLn $ X.ppElement $ xmlFeed populatedFeed'
45
46addItem' :: FilePath -> S.StateT FeedState IO ()
47addItem' mdFile = do
48 url <- S.liftIO $ mkUrl mdFile
49 fileStatus <- S.liftIO $ F.getFileStatus mdFile
50 fileContents <- S.liftIO $ readFile mdFile
51 let title = extract_title $ document
52 contents = writeAsciiDoc def document
53 document = readMarkdown def fileContents
54 (feed, time) <- S.get
55 let fileTime = maximum ([F.modificationTime, F.statusChangeTime] <-> fileStatus) :: System.Posix.Types.EpochTime
56 fileTime' = T.TOD (toInteger $ fromEnum fileTime) 0
57 let item = [ withItemTitle title
58 , withItemLink url
59 , withItemDate $ toFeedDateString feedKind fileTime'
60 , withItemDescription contents
61 ] <--> (newItem feedKind) :: Item
62 S.put (addItem item feed, if (Just fileTime' > time) then Just fileTime' else time)
63
64mkUrl :: FilePath -> IO String
65mkUrl link = do
66 status <- F.getFileStatus link
67 if F.isSymbolicLink status then
68 F.readSymbolicLink link >>= mkUrl
69 else
70 return $ mkUrl' link
71mkUrl' :: FilePath -> String
72mkUrl' path = (++) "http://dirty-haskell.org/posts/" $ switchExt ".md" ".html" $ FP.takeFileName path
73
74switchExt prev after str = if ('.':prev) `isSuffixOf` str then (dropWhileEnd (/= '.') str) ++ after else str
75
76(<->) :: [(a -> b)] -> a -> [b]
77[] <-> _ = []
78(f:fs) <-> x = (f x:fs <-> x)
79
80(<-->) :: [(a -> a)] -> a -> a
81[] <--> x = x
82(f:fs) <--> x = fs <--> (f x)