packages feed

muon 0.1.0.3 → 0.1.0.4

raw patch · 13 files changed

+212/−67 lines, 13 filesdep +happstack-server

Dependencies added: happstack-server

Files

README view
@@ -1,11 +1,11 @@ muon ==== Muon is a static blog generator, meaning that it takes files written in-convenient markup and converts it to HTML and CSS ready to deploy to a web-server.+convenient markup and converts it to HTML and CSS ready to deploy to a+web server. -Installing-----------+Installing from Darcs+--------------------- First, install the package by getting the darcs repo.      $ darcs get http://repos.kaashif.co.uk/muon@@ -15,9 +15,19 @@     $ cd muon     $ cabal install -After that, assuming you have configured cabal and/or your PATH correctly, muon-should be usable. Here are some things you may want to do:+After that, assuming you have configured cabal and/or your PATH+correctly, muon should be usable. Here are some things you may want to+do: +Installing from Hackage+-----------------------+Installing from Hackage using Cabal is as simple as:++    $ cabal install muon++Bear in mind this may not be the most up-to-date version, but it will be+a stable version.+ Using Muon ---------- Initialising a blog:@@ -34,14 +44,78 @@      $ muon generate -Notes------+Previewng the site locally:++    $ muon serve++Uploading site to server:++    $ muon upload++Multiple commands in sequence:++    $ muon init generate upload+    $ muon generate serve++Configuring Muon+----------------+After "muon init" is run, a file called "config.ini" is created. This is+where you configure the blog. By default, it should look like this:++    [site]+    title=Default site+    author=Your Name+    tagline=Something descriptive+    style=/style.css++    [remote]+    user=root+    server=webserver+    dir=/var/www/htdocs/++The [site] section needs little explanation - you can preview the site+yourself and see where those strings go. The "style" option denotes the+location of a custom CSS file.++The [remote] section is to configure the command run by Muon to upload+the site. The command is "rsync -a --delete site/ user@server:dir", with+the key words replaced with your SSH credentials on a server. If you're+not sure if the configuration is correct, remember: the directory must+end in a slash!++Extra Pages+-----------+Aside from a homepage, archive, and posts, you might want some extra+pages on your site, like "example.com/recipes" or "example.com/laptop".+You can add such pages to your site simply by creating a file with the+right name in the "pages/" directory of your blog.++For example, if your blog is at "myblog.com" and you want a page at+"myblog.com/mypage", edit the file "pages/mypage" and fill it with HTML.+Bear in mind, this content will go in between the "header" and "footer"+templates, so you don't need to include <body> or <html> tags. Here's+how you might do that:++    $ cat >> pages/mypage <<EOF+    <h2>My Custom Page</h2>+    <p>This is a page I made!</p>+    EOF++And that's that! Next time you "muon generate upload", the pages will be+accessible at "myblog.com/mypage".++Writing Posts+-------------+To add a new post, create a new file in the "posts/" directory with the+suffix ".post".+ When writing posts, make sure you put the title on the first line, the date on the second, and a short description (for the archive) on the third line. The-rest should be valid Markdown. See the posts/ directory after site+rest should be valid Markdown. See the "posts/" directory after site initialisation for some examples. -The posts are ordered lexicographically, _not_ by date. This means "aaa.post"-will always come before "bbb.post", regardless of the date contained in the file.--"muon upload" is currently hardcoded. Stay tuned for per-blog config files.+In the archive, posts are ordered lexicographically, _not_ by date.+This means "aaa.post" will always come above "bbb.post", regardless of+the date contained in the file itself. This allows you to decide the+order of your posts yourself, if you want to separate tutorials and+rants, for example.
muon.cabal view
@@ -2,16 +2,18 @@ -- see http://haskell.org/cabal/users-guide/  name:                muon-version:             0.1.0.3+version:             0.1.0.4 synopsis:            Static blog generator description:     Program which takes blog posts and pages written in Markdown and     compiles them into a tree of HTML pages which can then be served     by any web server.     .-    Muon is similar in function to Hakyll <http://jaspervdj.be/hakyll/>-    but has far fewer features (and dependencies) and is generally not-    ready for use in production as of yet.+    As of now, Muon supports:+    .+        * Generating a site from Markdown and HTML+        * Previewing a site locally using happstack-server+        * Uploading a site to a server using rsync homepage:            http://repos.kaashif.co.uk/darcs?r=muon;a=summary license:             BSD3 license-file:        LICENSE@@ -36,5 +38,5 @@  executable muon   main-is:             Main.hs-  build-depends:       base ==4.6.*, text ==0.11.*, HStringTemplate ==0.7.*, directory ==1.2.*, Glob ==0.7.*, process ==1.2.*, blaze-html ==0.7.*, markdown ==0.1.*, ConfigFile==1.1.*, MissingH==1.2.*+  build-depends:       base ==4.6.*, text ==0.11.*, HStringTemplate ==0.7.*, directory ==1.2.*, Glob ==0.7.*, process ==1.2.*, blaze-html ==0.7.*, markdown ==0.1.*, ConfigFile==1.1.*, MissingH==1.2.*, happstack-server==7.3.*   hs-source-dirs:      src
+ src/Config.hs view
@@ -0,0 +1,21 @@+module Config (getSetting, rsyncCmd) where++import System.Directory+import Data.ConfigFile+import Data.Either.Utils+import qualified Data.Text as T++blogCP ::  IO ConfigParser+blogCP = fmap forceEither $ readfile emptyCP "config.ini"++getSetting ::  String -> String -> IO String+getSetting sect c = do+    cp <- blogCP+    return $ forceEither $ get cp sect c++rsyncCmd ::  IO String+rsyncCmd = do+    user <- getSetting "remote" "user"+    server <- getSetting "remote" "server"+    dir <- getSetting "remote" "dir"+    return $ "rsync -av --delete site/ " ++ user ++ "@" ++ server ++ ":" ++ dir
src/Constant.hs view
@@ -4,6 +4,5 @@ import System.Directory  sitePath = "site/"-pageNames = ["about", "contact"] siteDirs = ["site", "style", "posts", "templates", "pages"]-mkdir = createDirectoryIfMissing False+mkdir = createDirectoryIfMissing True
src/Main.hs view
@@ -7,12 +7,14 @@ import System.Directory import System.FilePath.Glob import System.Environment-import System.Process (runCommand)+import System.Process (runInteractiveCommand) import Post (generatePosts) import Home (generateHome) import Archive (generateArchive) import Page (generatePages)+import Server (startServer) import Constant+import Config import Paths_muon  ensureDirs = mkdir sitePath@@ -35,7 +37,7 @@  copyStatic = do     copyFile "style/style.css" (sitePath ++ "style.css")-    runCommand $ "cp -R static " ++ sitePath ++ "static"+    runInteractiveCommand $ "cp -R static " ++ sitePath ++ "static"  generateSite = copyStatic             >> generatePosts@@ -46,20 +48,24 @@ showHelp = putStrLn "Usage: muon [commands]\n\n\ \  help        show this help message\n\ \  init        initialise a default blog in the current dir\n\-\  generate    generate static blog in 'site' directory\n\n\+\  generate    generate static blog in 'site' directory\n\+\  serve       serve site at localhost:8000\n\+\  upload      upload site to server\n\n\ \Report bugs to <kaashif@kaashif.co.uk>"  clearSite = mkdir sitePath          >> removeDirectoryRecursive sitePath          >> mkdir sitePath -rsyncCmd = "rsync -a --delete site/ root@webserver:/var/www/htdocs/"+printRun ::  String -> IO ()+printRun cmd = putStrLn ("Running \'" ++ cmd ++ "\'") >> runInteractiveCommand cmd >> return ()  proc ::  String -> IO () proc cmd     | cmd == "init" = createDefaults     | cmd == "generate" = clearSite >> generateSite-    | cmd == "upload" = void $ runCommand rsyncCmd+    | cmd == "serve" = putStrLn "Serving site at http://127.0.0.1:8000/" >> startServer+    | cmd == "upload" = rsyncCmd >>= printRun     | otherwise = showHelp  getArgsHelp = do
src/Page.hs view
@@ -6,13 +6,25 @@ import Site import Text.StringTemplate import Text.StringTemplate.GenericStandard+import System.Directory+import Control.Monad import Constant + pageTemplate = do     templates <- directoryGroup "templates" :: IO (STGroup T.Text)     let Just t = getStringTemplate "generic" templates     return t +onlyFiles ::  [FilePath] -> IO [FilePath]+onlyFiles fs = filterM doesFileExist fs++pageNames ::  IO [String]+pageNames = do+    cs <- getDirectoryContents "pages"+    let fs = map (\x -> "pages/" ++ x) cs+    fmap ( map (drop 6) ) (onlyFiles fs)+ renderPage ::  Site -> StringTemplate T.Text -> T.Text -> T.Text renderPage s t c = render                $ setAttribute "site" s@@ -35,4 +47,4 @@     writePage p c     putStrLn $ "Generated " ++ p -generatePages = mapM_ generatePage pageNames+generatePages = pageNames >>= mapM_ generatePage
src/Post.hs view
@@ -13,12 +13,16 @@ import Data.Typeable import Data.Data import Data.List+import Data.Char+import qualified Data.String.Utils as S import Site import Control.Monad import Constant  postPath = "posts/" :: String +replace a b c = S.replace a b (T.unpack c)+ data Post = Post { title :: T.Text                  , link :: T.Text                  , date :: T.Text@@ -36,8 +40,11 @@                $ setAttribute "site" s                $ setAttribute "post" p t -renderName ::  Site -> StringTemplate T.Text -> String -> IO T.Text-renderName s t n = liftM (renderPost s t) (getPost (0, n))+renderPostT ::  Post -> IO T.Text+renderPostT p = do+    t <- postTemplate+    s <- readSite+    return $ renderPost s t p  makeExtract ::  Post -> T.Text makeExtract p = T.pack@@ -48,55 +55,54 @@                  ++ "<br/><a href=\'" ++ T.unpack (link p) ++ "\'>Read more...</a>"                  ++ "<br/><br/><hr/>" -makePost ::  (Int, [String]) -> Post-makePost l = Post { title  = T.pack $ head (snd l)-                  , link = T.pack $ "/post/" ++ show (fst l)-                  , date = T.pack $ snd l !! 1-                  , comment = T.pack $ snd l !! 2-                  , content = T.pack $ extractContent (snd l) }+makePost ::  [String] -> Post+makePost l = Post { title  = T.pack $ head l+                  , link = T.pack $ "/" ++ S.replace "-" "/" (l !! 1) ++ "/" ++ linkify (head l)+                  , date = T.pack $ l !! 1+                  , comment = T.pack $ l !! 2+                  , content = T.pack $ extractContent l+                  }  extractContent ::  [String] -> String extractContent l = TL.unpack+                 $ TL.replace "<pre>" "<pre class=\'prettyprint\'>"                  $ renderHtml                  $ markdown def                  $ TL.pack                  $ unlines                  $ drop 3 l -getPost ::  (Int, FilePath) -> IO Post+getPost ::  FilePath -> IO Post getPost n = do-    c <- readFile (snd n)-    return $ makePost (fst n, lines c)+    c <- readFile n+    return $ makePost $ lines c -getNames ::  IO [(Int, FilePath)]+getNames ::  IO [FilePath] getNames = do     d <- globDir [compile "*.post"] postPath-    let l = (sort . head . fst) d-    return $ zip [1..(length l)] l+    return $ (sort . head . fst) d -renderPosts ::  IO [T.Text]-renderPosts = do-    templates <- directoryGroup "templates" :: IO (STGroup T.Text)-    let Just t = getStringTemplate "post" templates-    ns <- getNames-    s <- readSite-    mapM (renderName s t . snd) ns+linkify ::  [Char] -> [Char]+linkify s = filter isLetter $ map toLower $ S.replace " " "-" s -writePosts ::  [T.Text] -> IO ()-writePosts ps = mapM_ writePost (zip [1..(length ps)] ps)+writePosts ::  [Post] -> IO ()+writePosts ps = mapM_ writePost ps -writePost ::  (Int, T.Text) -> IO ()+writePost ::  Post -> IO () writePost p = do-    mkdir $ sitePath ++ "post"-    mkdir $ sitePath ++ "post/" ++ show (fst p)-    writeFile (sitePath ++ "post/" ++ show (fst p) ++ "/index.html") (T.unpack $ T.append "\n" $ snd p)+    let d = S.replace "-" "/" (T.unpack $ date p) ++ "/" ++ (linkify $ T.unpack $ title p)+    mkdir $ sitePath ++ d+    c <- renderPostT p+    writeFile (sitePath ++ d ++ "/index.html") (T.unpack $ T.append "\n" c) +getAllPosts ::  IO [Post] getAllPosts = do     ns <- getNames     mapM getPost ns +getAllExtracts ::  IO [T.Text] getAllExtracts = do     ps <- getAllPosts     return $ map makeExtract ps -generatePosts = renderPosts >>= writePosts >> putStrLn "Generated posts"+generatePosts = getAllPosts >>= writePosts >> putStrLn "Generated posts"
+ src/Server.hs view
@@ -0,0 +1,7 @@+module Server where++import Happstack.Server ( Browsing(EnableBrowsing), nullConf+                        , serveDirectory, simpleHTTP+                        )+startServer ::  IO ()+startServer = simpleHTTP nullConf $ serveDirectory EnableBrowsing ["index.html"] "site/"
src/Site.hs view
@@ -7,6 +7,7 @@ import Data.Data import Data.ConfigFile import Data.Either.Utils+import Config  data Site = Site { title :: T.Text                  , style :: T.Text@@ -20,15 +21,14 @@                    , tagline = "Description of this blog"                    } -getSetting ::  ConfigParser -> String -> T.Text-getSetting cp s = T.pack $ forceEither $ get cp "site" s- readSite ::  IO Site readSite = do-    r <- readfile emptyCP "config.ini"-    let cp = forceEither r-    return $ Site { title = getSetting cp "title"-                  , style = getSetting cp "style"-                  , author = getSetting cp "author"-                  , tagline = getSetting cp "tagline"+    t <- getSetting "site" "title"+    s <- getSetting "site" "style"+    a <- getSetting "site" "author"+    g <- getSetting "site" "tagline"+    return $ Site { title = T.pack t+                  , style = T.pack s+                  , author = T.pack a+                  , tagline = T.pack g                   }
src/def/config.ini view
@@ -3,3 +3,8 @@ author=Your Name tagline=Something descriptive style=/style.css++[remote]+user=root+server=webserver+dir=/var/www/htdocs/
src/def/posts/first.post view
@@ -2,4 +2,13 @@ 2014-04-05 A comment -Some content+Something interesting. Here is some highlighted code:++    #include <stdio.h>+    +    int main()+    {+        printf("Hello, world!\n");+        return 0;+    }+
src/def/style/style.css view
@@ -129,7 +129,7 @@ 	padding: 20px; 	background: #DDDDDD; 	color: #333333;-	margin: 0 -20px 20px;+	margin: 0; 	overflow-x:auto; } li pre {
src/def/templates/header.st view
@@ -3,6 +3,12 @@ <head> <title>$site.title$</title> <link rel="stylesheet" type="text/css" href="$site.style$">+<script type="text/javascript"+  src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">+</script>+<script +  src="https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst">+</script> </head> <body> <div class="wrapper">@@ -18,8 +24,6 @@             <li> <a href="/contact">Contact</a></li>             <li>//</li>             <li> <a href="/archive">Archive</a></li>-            <li>//</li>-            <li> <a href="http://git.kaashif.co.uk/">Code</a></li>         </ul> </header> <hr id="header" />