site: commit and use hakyll-std, a generic site builder

This commit is contained in:
Simon Michael 2015-07-13 20:34:07 -07:00
parent 7d81ca0e8f
commit f788c53217
7 changed files with 321 additions and 8 deletions

View File

@ -817,19 +817,27 @@ $(call def-help-subsection,DOCUMENTATION:)
# \
# )
site: \
$(call def-help,site, generate the hledger.org website with hakyll-std (a generic hakyll script) ) #olddocs
-cd doc/site; hakyll build
doc/site/hakyll-std hakyll-std: \
doc/site/hakyll-std.hs \
doc/site/TableOfContents.hs \
doc/site/hakyll-std.cabal \
doc/site/stack.yaml \
$(call def-help,hakyll-std, build a generic hakyll site builder script )
cd doc/site; stack ghc hakyll-std
site-clean: \
site: doc/site/hakyll-std \
$(call def-help,site, generate the hledger.org website with hakyll-std )
-cd doc/site; ./hakyll-std build
site-clean: doc/site/hakyll-std \
$(call def-help,site-clean, remove hakyll-generated files (& take down the website) ) #cleanolddocs
-cd doc/site; hakyll clean
-cd doc/site; ./hakyll-std clean
# rm -rf doc/site/_site/*
# XXX hakyll preview/watch mostly don't live-update any more
site-preview: \
# XXX hakyll watch & preview mostly don't live-update any more
site-preview: doc/site/hakyll-std \
$(call def-help,site-preview, run a hakyll server to preview the website ) #doc/site/site
cd doc/site; hakyll preview
-cd doc/site; ./hakyll-std watch # -h hledger.org
# site-view: site \
# $(call def-help,site-view,\

30
doc/site/LICENSE Normal file
View File

@ -0,0 +1,30 @@
Copyright (c) 2015
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Your name here nor the names of other
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

2
doc/site/Setup.hs Normal file
View File

@ -0,0 +1,2 @@
import Distribution.Simple
main = defaultMain

View File

@ -0,0 +1,82 @@
{-# LANGUAGE OverloadedStrings #-}
-- from https://github.com/blaenk/blaenk.github.io
module TableOfContents (
tableOfContents,
ignoreTOC,
collectHeaders,
removeTOCMarker
) where
import Text.Pandoc
import Text.Pandoc.Walk (walk, query)
import Data.List (groupBy)
import Data.Tree (Forest, Tree(Node))
import Data.Monoid ((<>), mconcat)
import Data.Function (on)
import Data.Maybe (fromMaybe)
import Text.Blaze.Html (preEscapedToHtml, (!))
import Text.Blaze.Html.Renderer.String (renderHtml)
import qualified Text.Blaze.Html5 as H
import qualified Text.Blaze.Html5.Attributes as A
headerLevel :: Block -> Int
headerLevel (Header level _ _) = level
headerLevel _ = error "not a header"
ignoreTOC :: Block -> Block
ignoreTOC (Header level (ident, classes, params) inline) =
Header level (ident, "notoc" : classes, params) inline
ignoreTOC x = x
removeTOCMarker :: Block -> Block
removeTOCMarker (BulletList (( (( Plain ((Str "toc"):_)):_)):_)) = Null
removeTOCMarker x = x
collectHeaders :: Block -> [Block]
collectHeaders header@(Header _ (_, classes, _) _) =
if "notoc" `elem` classes
then []
else [header]
collectHeaders _ = []
groupByHierarchy :: [Block] -> Forest Block
groupByHierarchy = map (\(x:xs) -> Node x (groupByHierarchy xs)) . groupBy ((<) `on` headerLevel)
markupHeader :: Tree Block -> H.Html
markupHeader (Node (Header _ (ident, _, keyvals) inline) headers)
| headers == [] = H.li $ link
| otherwise = H.li $ link <> (H.ol $ markupHeaders headers)
where render x = writeHtmlString def (Pandoc nullMeta [(Plain x)])
section = fromMaybe (render inline) (lookup "toc" keyvals)
link = H.a ! A.href (H.toValue $ "#" ++ ident) $ preEscapedToHtml section
markupHeader _ = error "what"
markupHeaders :: Forest Block -> H.Html
markupHeaders = mconcat . map markupHeader
createTable :: Forest Block -> H.Html
createTable headers =
(H.nav ! A.id "toc") $ do
H.p "Contents"
H.ol $ markupHeaders headers
generateTOC :: [Block] -> String -> Block -> Block
generateTOC [] _ x = x
generateTOC headers alignment x@(BulletList (( (( Plain ((Str "toc"):_)):_)):_))
| alignment == "right" = render . (! A.class_ "right-toc") . table $ headers
| alignment == "left" = render . table $ headers
| otherwise = x
where render = (RawBlock "html") . renderHtml
table = createTable . groupByHierarchy
generateTOC _ _ x = x
tableOfContents :: String -> Pandoc -> Pandoc
tableOfContents alignment ast =
if alignment /= "off"
then let headers = query collectHeaders ast
in walk (generateTOC headers alignment) ast
else walk ignoreTOC ast

39
doc/site/hakyll-std.cabal Normal file
View File

@ -0,0 +1,39 @@
name: hakyll-std
version: 0.1.0
synopsis: Generic hakyll site builder script.
description: Generic hakyll site builder script.
homepage: http://github.com/simonmichael/hledger
license: BSD3
license-file: LICENSE
author: Simon Michael
maintainer: simon@joyful.com
-- copyright:
category: Web
build-type: Simple
-- extra-source-files:
cabal-version: >=1.10
-- library
-- hs-source-dirs: src
-- build-depends: base >= 4.7 && < 5
-- default-language: Haskell2010
executable hakyll-std
default-language: Haskell2010
ghc-options: -threaded -rtsopts -with-rtsopts=-N
hs-source-dirs: .
main-is: hakyll-std.hs
other-modules: TableOfContents
build-depends: base >= 4.7 && < 5
,hakyll >=4.7
,pandoc >=1.15
,pandoc-types
,process
,directory
,data-default
,blaze-html
,containers
-- source-repository head
-- type: git
-- location: https://github.com/simonmichael/hledger

146
doc/site/hakyll-std.hs Executable file
View File

@ -0,0 +1,146 @@
#!/usr/bin/env stack
-- stack --resolver nightly-2015-07-01 --install-ghc runghc --package hakyll --package pandoc
{-# LANGUAGE OverloadedStrings #-}
{- |
A simple hakyll website builder suitable for software project sites,
intended to be used as-is without recompilation. Functionality:
- copies these static files to _site/ :
*.{html,htm,css,js,gif,jpg,jpeg,png}
{css,img,js,files}/** (** means everything below)
site/{css,img,js,files,etc}/**
doc/**.{html,htm,txt,gif,jpg,jpeg,png}
- renders these markdown files to _site/*.html :
*.{md,mdwn,markdown}
doc/**.{md,mdwn,markdown}
- applies this template file to markdown content:
site.tmpl or site/site.tmpl (the first found)
- a single markdown list item containing the word "toc" is replaced by
a table of contents based on headings
- syntax highlighting of fenced code blocks in markdown is enabled
(if you provide suitable kate styles, eg a syntax.css)
Usage:
$ hakyll-std [--help|clean|build|preview|...] # standard hakyll options
-}
import Control.Monad
import Data.Default
import Hakyll
import System.Directory
import System.Environment (getArgs)
import System.Exit (exitSuccess)
import System.Process (system)
-- import Text.Highlighting.Kate (pygments, kate, espresso, tango, haddock, monochrome, zenburn)
import Text.Pandoc.Options
import TableOfContents (tableOfContents)
import Debug.Trace
strace :: Show a => a -> a
strace a = trace (show a) a
filesToCopy =
["site/css/**"
,"site/js/**"
,"site/img/**"
,"site/images/**"
,"site/fonts/**"
,"site/files/**"
,"site/etc/**"
,"site/*.html"
,"site/*.htm"
,"site/*.gif"
,"site/*.jpg"
,"site/*.jpeg"
,"site/*.png"
,"site/*.css"
,"site/*.js"
,"css/**"
,"js/**"
,"img/**"
,"images/**"
,"fonts/**"
,"files/**"
,"doc/**.html"
,"doc/**.htm"
,"doc/**.txt"
,"doc/**.gif"
,"doc/**.jpg"
,"doc/**.jpeg"
,"doc/**.png"
,"*.html"
,"*.htm"
,"*.css"
,"*.js"
,"*.gif"
,"*.jpg"
,"*.jpeg"
,"*.png"
]
filesToRender =
["*.md"
,"*.mdwn"
,"*.markdown"
,"doc/**.md"
,"doc/**.mdwn"
,"doc/**.markdown"
]
-- http://hackage.haskell.org/package/pandoc-1.13/docs/src/Text-Pandoc-Options.html#ReaderOptions
pandocReaderOptions = def
-- http://hackage.haskell.org/package/pandoc-1.13/docs/src/Text-Pandoc-Options.html#WriterOptions
pandocWriterOptions = def
{writerHighlight=True
-- this would change the value of pandoc's $highlight-css$ var
-- for now, let the user provide these styles
-- ,writerHighlightStyle=tango
}
pandocTransform = tableOfContents "right"
main = do
args <- getArgs
when (any (`elem` args) ["--version"]) $ do
putStrLn "hakyll standard site builder v0.1"
exitSuccess
hakyll $ do
match (foldl1 (.||.) filesToCopy) $ route idRoute >> compile copyFileCompiler
-- there might or might not be a site template in ./ or ./site/
mtmpl <- preprocess $ do
t1 <- doesFileExist "site.tmpl"
t2 <- doesFileExist "site/site.tmpl"
return $ case (t1, t2) of (False, True) -> Just "site/site.tmpl"
(True, _) -> Just "site.tmpl"
(False, False) -> Nothing
case mtmpl of
Just tmpl -> match tmpl $ compile templateCompiler
Nothing -> return ()
match (foldl1 (.||.) filesToRender) $ do
route $ setExtension "html"
compile $
pandocCompilerWithTransformM pandocReaderOptions pandocWriterOptions (return . pandocTransform)
>>= (case mtmpl of
Just tmpl -> loadAndApplyTemplate (fromCapture tmpl "") defaultContext
Nothing -> return)
>>= relativizeUrls
-- this fails the first time after a clean because it runs before README.html generation
-- when ("build" `elem` args) $ preprocess linkReadmeToIndex
-- can't do anything here, hakyll exits
linkReadmeToIndex = system "ln -sf README.html _site/index.html" >> return ()

6
doc/site/stack.yaml Normal file
View File

@ -0,0 +1,6 @@
# stack.yaml for hakyll-std
extra-deps: []
resolver: nightly-2015-07-01
flags: {}
packages:
- '.'