// Date: Dec 5, 2013
-
+//
// Use Bourbon
@import 'sass/bourbon/bourbon'
@@ -28,28 +28,53 @@
@import 'sass/blog-page'
@import 'sass/contact-page'
@import 'sass/tag-page'
-
+@import 'sass/post-page'
@import 'sass/src-highlight'
//-------------------------------------------------------------------------------------
// General
//-------------------------------------------------------------------------------------
+*
+ -webkit-backface-visibility: hidden
+
body
background: #efe
font: 14px/21px FreeMono, monospace, Helvetica, Arial, sans-serif
- -webkit-text-stroke: 0.3px
h1,h2,h3,h4,h5,h6
font-family: FreeMono
+h1
+ font-size: 2.5em
+h2
+ font-size: 2em
+h3
+ font-size: 1.75em
+h4
+ font-size: 1.5em
+h5
+ font-size: 1.25em
+h6
+ font-size: 1em
+
+ul, ol
+ padding-left: 1em
+
+hr
+ margin-bottom: 0.5em
+
+#noscript-alert
+ @include border-box(0, #FCD4D4)
+ text-align: center
#page-content
opacity: 1
- @include transition(opacity 400ms)
+ @include transition(opacity 250ms ease-out)
+ margin-top: 1em
overflow: hidden
ul > li:before
- content: "\2192 "
- padding-right: 1em
+ content: "\2192"
+ padding-right: 0.5em
font-size: 1.5em
ul > li
@@ -58,16 +83,19 @@ h1,h2,h3,h4,h5,h6
margin-bottom: 0.02em
#page-content.loading
- opacity: 0.45
+ opacity: 0.35
-#page-content.init.loading
- background: url('/images/init-loading.gif') no-repeat 50%
- height: 100px
- padding: 1.5em 0
+#page-content.loading-done
+ @include transition(opacity 1s ease-in 0.5s)
+ opacity: 1
#page-content.loading-error
// do something
+#page-content.init.loading
+ background: url('/images/init-loading.gif') no-repeat 50%
+ height: 125px
+
#page-content.init.loading-error
// do something
@@ -77,7 +105,7 @@ h1,h2,h3,h4,h5,h6
#footer-right
text-align: right
-.container.border-box
+.border-box
@include border-box()
//-------------------------------------------------------------------------------------
diff --git a/site.hs b/site.hs
index d6bcf19..cb3c2f6 100644
--- a/site.hs
+++ b/site.hs
@@ -1,7 +1,7 @@
---------------------------------------------------------------------------------------------------------
{-# LANGUAGE OverloadedStrings, TupleSections #-}
---------------------------------------------------------------------------------------------------------
--- (C) Copyright Collin Doering @!@YEAR@!@
+-- (C) Copyright Collin Doering 2013
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
@@ -24,11 +24,17 @@
import Hakyll
import Control.Monad
+import Data.Char (chr)
import Data.Monoid (mappend,mconcat,(<>))
-import Data.List (sortBy)
+import Data.Maybe (maybeToList)
+import Data.List (sortBy,intercalate)
import Data.Ord (comparing)
import Data.Functor ((<$>))
-import System.FilePath ((>))
+import Data.Time.Format (parseTime)
+import System.Locale (defaultTimeLocale)
+import Data.Time.Clock (UTCTime)
+import System.Random
+import System.FilePath (takeBaseName,takeFileName,(>))
import System.FilePath.Posix (takeBaseName)
import Text.Parsec
@@ -46,28 +52,74 @@ feedConfig :: FeedConfiguration
feedConfig = feedConfiguration Nothing
main :: IO ()
-main = hakyllWith myConfig $ do
+main = do
+ -- Get a random number generator before going into Rules monad
+ stdGen <- getStdGen
+
+ hakyllWith myConfig $ do
-- All Versions ------------------------------------------------------------------------------------------
match "action/**" $ do
route idRoute
compile copyFileCompiler
- match (fromRegex "^sass/default.s[ac]ss$") $ do
+ pageIds <- getMatches "pages/**"
+ fontIds <- getMatches "fonts/**"
+ imageIds <- getMatches "images/**"
+ cssIds <- getMatches "css/**"
+ jsIds <- getMatches "js/**"
+ libIds <- getMatches "lib/**"
+
+ allSassIds <- getMatches "sass/**"
+ let sassIds = filter (`notElem` badIds) allSassIds
+ badIds = filterMatches (fromRegex "^sass/bourbon/.*$|^sass/default.s[ac]ss$") allSassIds
+ manifestIds = sassIds ++ fontIds ++ imageIds ++ pageIds ++ cssIds ++ libIds ++ jsIds
+
+ sassDeps <- makePatternDependency $ fromList sassIds
+ manifestDeps <- makePatternDependency $ fromList manifestIds
+
+ rulesExtraDependencies [sassDeps] $ match (fromRegex "^sass/default.s[ac]ss$") $ do
route $ gsubRoute "sass/" (const "") `composeRoutes` setExtension "css"
- compile $ getResourceBody >>= withItemBody (fmap compressCss . unixFilter "sass" [])
+ compile $ getResourceBody
+ >>= saveSnapshot "original"
+ >>= withItemBody (fmap compressCss . unixFilter "sass" [])
+
+ rulesExtraDependencies [manifestDeps] $ create ["manifest.appcache"] $ do
+ route idRoute
+ compile $ do
+ manifestCacheRoutesMaybe <- sequence $ liftM getRoute (fontIds ++ pageIds ++ imageIds ++ cssIds ++ libIds ++ jsIds)
+ let randomNum = random stdGen :: (Int, StdGen)
+ randomStr = show $ fst $ randomNum
+ manifestStart = unlines [ "CACHE MANIFEST"
+ , "# " ++ randomStr
+ , "" ]
+ manifestCacheSingles = unlines [ "/index.html"
+ , "/default.css" ]
+ manifestCache = unlines $ filter (not . null) $ fmap (maybe "" ("/"++)) manifestCacheRoutesMaybe
+ manifestFallback = unlines [""
+ , "FALLBACK:"
+ , "/posts/ /post-offline.html"
+ , "/tags/ /tags-offline.html"
+ , "" ]
+ manifestNetwork = unlines [ "NETWORK:"
+ , "*"
+ , "" ]
+ makeItem $ manifestStart ++ manifestCacheSingles ++ manifestCache ++ manifestFallback ++ manifestNetwork
+
+ -- TODO: This needs to be more robust
+ match "*-offline.html" $ do
+ route idRoute
+ compile copyFileCompiler
match "css/**" $ do
route idRoute
compile compressCssCompiler
- match "lib/Skeleton/stylesheets/*.css" $ do
- route $ gsubRoute "Skeleton/stylesheets" (const "css")
+ match "lib/Skeleton/*.css" $ do
+ route $ gsubRoute "Skeleton" (const "css")
compile compressCssCompiler
- forM_ [("images/**", idRoute),
- ("fonts/**", idRoute),
- ("lib/Skeleton/images/*",
- gsubRoute "Skeleton" $ const "")] $ \(p, r) ->
+ forM_ [ ("images/**", idRoute)
+ , ("fonts/**", idRoute) ] $ \(p, r) ->
match p $ do
route r
compile copyFileCompiler
@@ -79,10 +131,22 @@ main = hakyllWith myConfig $ do
tags <- buildTags ("posts/**" .&&. hasNoVersion) (fromCapture "tags/*.html")
tagsRules tags $ genTagRules tags
- -- paginatedPosts <- buildPaginateWith 2 (\n -> fromFilePath $ "blog/page" ++ show n ++ ".html") ("posts/**" .&&. hasNoVersion)
+ -- paginatedPosts <- buildPaginateWith 3 (\n -> fromFilePath $ "blog/page" ++ show n ++ ".html") ("posts/**" .&&. hasNoVersion)
-- paginatedPosts <- buildPaginate ("posts/**" .&&. hasNoVersion)
-- paginateRules paginatedPosts (genPaginateRules tags paginatedPosts)
+ -- paginate 3 $ \index maxIndex itemsForPage -> do
+ -- let id = fromFilePath $ "blog/page" ++ show index ++ ".html"
+ -- create [id] $ do
+ -- route idRoute
+ -- compile $ do
+ -- -- items <- sequence $ map loadTeaser itemsForPage
+ -- -- let itemBodies = map itemBody items
+ -- -- postCtx = defaultContext -- TODO
+ -- makeItem ""
+ -- >>= saveSnapshot "content"
+ -- >>= loadAndApplyTemplate "templates/pages/blog.haml" (taggedPostCtx tags)
+
match "pages/*" $ do
route $ setExtension "html"
compile $ do
@@ -103,21 +167,14 @@ main = hakyllWith myConfig $ do
pg <- loadSnapshot (fromFilePath pageTemplate) "original"
>>= withItemBody (unixFilter "haml" [])
>>= applyAsTemplate (sectionCtx <> masterCtx)
- >>= loadAndApplyTemplate "templates/page.haml" defaultContext
makeItem . itemBody $ pg
- -- pandocCompiler
- -- >>= loadAndApplyTemplate (fromFilePath pageTemplate) masterCtx
- -- >>= loadAndApplyTemplate "templates/page.haml" defaultContext
--- >>= relativizeUrls
-
-- TODO: add "next" and "previous" while processing templates/partials/post.haml
match "posts/**" $ do
route $ setExtension "html"
compile $ pandocCompiler
>>= saveSnapshot "content"
>>= loadAndApplyTemplate "templates/partials/post.haml" (taggedPostCtx tags)
- >>= loadAndApplyTemplate "templates/page.haml" defaultContext
-- >>= relativizeUrls
create ["atom.xml"] $ do
@@ -129,7 +186,7 @@ main = hakyllWith myConfig $ do
renderAtom feedConfig feedCtx blogPosts
forM_ [("js/**", idRoute),
- ("lib/JQuery/*", gsubRoute "JQuery" $ const $ "js"),
+ ("lib/JQuery/*", gsubRoute "JQuery" $ const "js"),
("lib/jquery-address/src/jquery.address.js",
customRoute $ const "lib/js/jquery.address.js")] $ \(p, r) ->
match p $ do
@@ -148,6 +205,7 @@ main = hakyllWith myConfig $ do
>>= applyAsTemplate indexCtx
>>= loadAndApplyTemplate "templates/default.haml" indexCtx
>>= relativizeUrls
+
---------------------------------------------------------------------------------------------------------
-- NOJS Version -----------------------------------------------------------------------------------------
-- -- tagsNoJs <- buildTags ("posts/**" .&&. hasVersion "nojs") (fromCapture "nojs/tags/*.html")
@@ -269,7 +327,6 @@ genTagRules tags tag pattern = do
makeItem ""
>>= loadAndApplyTemplate "templates/tag-page.haml" tagPageCtx
- >>= loadAndApplyTemplate "templates/page.haml" defaultContext
version "rss" $ do
route $ gsubRoute " " (const "-") `composeRoutes` setExtension "xml"
@@ -277,13 +334,40 @@ genTagRules tags tag pattern = do
>>= fmap (take 10) . recentFirst
>>= renderAtom (feedConfiguration $ Just tag) (bodyField "description" <> defaultContext)
--- genPaginateRules :: Tags -> Paginate -> PageNumber -> Pattern -> Rules ()
--- genPaginateRules tags paginate n pattern = do
--- route $ idRoute
--- compile $ pandocCompiler
--- >>= loadAndApplyTemplate "templates/partials/post.haml" (taggedPostCtx tags <> paginateContext paginate)
--- >>= loadAndApplyTemplate "templates/page.haml" defaultContext
--- >>= relativizeUrls
+genPaginateRules :: Tags -> Paginate -> PageNumber -> Pattern -> Rules ()
+genPaginateRules tags paginate n pattern = do
+ route idRoute
+ compile $ pandocCompiler
+ >>= loadAndApplyTemplate "templates/partials/post.haml" (taggedPostCtx tags <> paginateContext paginate)
+-- >>= loadAndApplyTemplate "templates/page.haml" defaultContext
+-- >>= relativizeUrls
+
+-- | Split list into equal sized sublists.
+-- https://github.com/ian-ross/blog
+chunk :: Int -> [a] -> [[a]]
+chunk n [] = []
+chunk n xs = ys : chunk n zs
+ where (ys,zs) = splitAt n xs
+
+paginate:: Int -> (Int -> Int -> [Identifier] -> Rules ()) -> Rules ()
+paginate itemsPerPage rules = do
+ identifiers <- getMatches "posts/*"
+
+ let sorted = sortBy (flip byDate) identifiers
+ chunks = chunk itemsPerPage sorted
+ maxIndex = length chunks
+ pageNumbers = take maxIndex [1..]
+ process i is = rules i maxIndex is
+ zipWithM_ process pageNumbers chunks
+ where
+ byDate id1 id2 =
+ let fn1 = takeFileName $ toFilePath id1
+ fn2 = takeFileName $ toFilePath id2
+ parseTime' fn = parseTime defaultTimeLocale "%Y-%m-%d" $ intercalate "-" $ take 3 $ splitAll "-" fn
+ in compare (parseTime' fn1 :: Maybe UTCTime) (parseTime' fn2 :: Maybe UTCTime)
+
+
+
loadVersion :: String -> Identifier -> Compiler (Item String)
loadVersion v i = load (setVersion (listAsMaybe v) i) >>= makeItem . itemBody
diff --git a/tags-offline.html b/tags-offline.html
new file mode 100644
index 0000000..586d0be
--- /dev/null
+++ b/tags-offline.html
@@ -0,0 +1,9 @@
+
+
+
+
+
+
You are currently offline and this tag page is unaccesable
+
+
+
diff --git a/templates/default.haml b/templates/default.haml
index e12428c..a2306d9 100644
--- a/templates/default.haml
+++ b/templates/default.haml
@@ -3,7 +3,8 @@
/[if IE 7]
-%html.en
+%html.en(manifest='manifest.appcache')
+ // Work in progress on application cache;
%head
/ Basic Page Needs
%meta(charset="utf-8")
@@ -34,17 +35,18 @@
// %link(rel="apple-touch-icon" sizes="72x72" href="lib/images/apple-touch-icon-72x72.png")
// %link(rel="apple-touch-icon" sizes="114x114" href="lib/images/apple-touch-icon-114x114.png")
- %noscript
- #noscript-alert.container
- .alert.alert-danger
- %h1 This site requires javascript!
- %p
- If you insist on not using javascript we provide a simplified website
- %a.alert-link(href="nojs/pages") here
%body
$partial("templates/partials/logo-banner.haml")$
$partial("templates/partials/nav.haml")$
- #page-content.sixteen.columns.container.init.loading
+
+ #page-content.init.loading
+ %noscript
+ #noscript-alert.container
+ %h1 This site requires javascript!
+ %p
+ If you insist on not using javascript we provide a simplified website
+ %a.alert-link(href="nojs/index.html") here
+
$partial("templates/partials/footer.haml")$
/ External javascript libraries: JQuery, and JQuery-Address
diff --git a/templates/page.haml b/templates/page.haml
deleted file mode 100644
index 967232f..0000000
--- a/templates/page.haml
+++ /dev/null
@@ -1,2 +0,0 @@
-#page-content.sixteen.columns
- $body$
diff --git a/templates/pages/contact.haml b/templates/pages/contact.haml
index 584d198..583ee0e 100644
--- a/templates/pages/contact.haml
+++ b/templates/pages/contact.haml
@@ -1,3 +1,6 @@
#contact-page.container.border-box
- .sixteen.columns
+ .row
+ #about-me-box
+ %p about me card here
+ #about-me-blurb.row
$body0$
diff --git a/templates/pages/home.haml b/templates/pages/home.haml
index 533f71d..c1632cc 100644
--- a/templates/pages/home.haml
+++ b/templates/pages/home.haml
@@ -1,16 +1,20 @@
#home-page.container.border-box
- .eight.columns.alpha
- %h1 About Me
- #about-me-box
- $aboutMe$
- .seven.columns.offset-by-one.omega
- #recent-posts
- %h1 Recent Posts
- %hr/
- $partial("templates/partials/recent-posts-list.haml")$
- #tag-cloud
- %h1 Tag Cloud
- %hr/
- $tagCloud$
- .sixteen.columns
- $tools$
+ .row
+ .eight.columns.alpha
+ %h1 About Me
+ #about-me-box
+ $aboutMe$
+ .seven.columns.offset-by-one.omega
+ #recent-posts
+ %h1 Recent Posts
+ %hr/
+ $partial("templates/partials/recent-posts-list.haml")$
+ #tag-cloud
+ %h1 Tag Cloud
+ %hr/
+ $tagCloud$
+ .row
+ #license.eight.columns.alpha
+ $license$
+ #tools.seven.columns.offset-by-one.omega
+ $tools$
diff --git a/templates/partials/footer.haml b/templates/partials/footer.haml
index 15b6285..c284c00 100644
--- a/templates/partials/footer.haml
+++ b/templates/partials/footer.haml
@@ -1,11 +1,9 @@
-#footer-wrap.sixteen.columns
+#footer-wrap
.container
%footer
#footer-left.eight.columns.alpha
- %p
- ©
- %a(href="/") RekahSoft 2013
+ %p © Collin Doering 2013
#footer-right.eight.columns.omega
%p
- Proudly generated by
- %a(href="http://jaspervdj.be/hakyll") Hakyll
+ Proudly crafted using
+ %a(href="https://www.gnu.org/philosophy/free-sw.html") Free Software
diff --git a/templates/partials/logo-banner.haml b/templates/partials/logo-banner.haml
index fe7bdde..7c4eef9 100644
--- a/templates/partials/logo-banner.haml
+++ b/templates/partials/logo-banner.haml
@@ -1,3 +1,3 @@
-#logo-background.sixteen.columns
+#logo-background
#logo.container
diff --git a/templates/partials/nav-nojs.haml b/templates/partials/nav-nojs.haml
index d71f62a..7a2ebab 100644
--- a/templates/partials/nav-nojs.haml
+++ b/templates/partials/nav-nojs.haml
@@ -1,4 +1,4 @@
-#nav.sixteen.columns
+#nav
%ul#nav-menu
$for(pagesFirst)$
%li
diff --git a/templates/partials/nav.haml b/templates/partials/nav.haml
index 8e53925..664b4b9 100644
--- a/templates/partials/nav.haml
+++ b/templates/partials/nav.haml
@@ -1,4 +1,4 @@
-#nav.sixteen.columns.loading
+#nav.loading
%ul#nav-menu
$for(pages)$
%li
diff --git a/templates/tag-page.haml b/templates/tag-page.haml
index 7f93045..21a7db6 100644
--- a/templates/tag-page.haml
+++ b/templates/tag-page.haml
@@ -1,4 +1,4 @@
-#tag-page
+#tag-page.container
%h1#tag $tag$
$for(posts)$
$partial("templates/partials/post-teaser.haml")$