tools/pandoc-site.hs, Shake.hs: pandoc filter version of hakyll-std website builder
This commit is contained in:
parent
01dec66151
commit
bac12543df
6
Shake.hs
6
Shake.hs
@ -69,6 +69,7 @@ usage = unlines
|
|||||||
]
|
]
|
||||||
|
|
||||||
pandoc = "stack exec -- pandoc" -- pandoc from project's stackage snapshot
|
pandoc = "stack exec -- pandoc" -- pandoc from project's stackage snapshot
|
||||||
|
pandocSiteFilter = "tools/pandoc-site"
|
||||||
hakyllstd = "site/hakyll-std/hakyll-std"
|
hakyllstd = "site/hakyll-std/hakyll-std"
|
||||||
makeinfo = "makeinfo"
|
makeinfo = "makeinfo"
|
||||||
-- nroff = "nroff"
|
-- nroff = "nroff"
|
||||||
@ -305,6 +306,11 @@ main = do
|
|||||||
,"and try again."
|
,"and try again."
|
||||||
])
|
])
|
||||||
|
|
||||||
|
pandocSiteFilter %> \out -> do
|
||||||
|
let source = out <.> "hs"
|
||||||
|
need [source]
|
||||||
|
cmd "stack --stack-yaml=stack-ghc8.2.yaml ghc --package pandoc -- -o" out source
|
||||||
|
|
||||||
-- cleanup
|
-- cleanup
|
||||||
|
|
||||||
phony "clean" $ do
|
phony "clean" $ do
|
||||||
|
|||||||
1
tools/.gitignore
vendored
1
tools/.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
generatetimeclock
|
generatetimeclock
|
||||||
|
pandoc-site
|
||||||
|
|||||||
83
tools/pandoc-site.hs
Normal file
83
tools/pandoc-site.hs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
-- from https://github.com/blaenk/blaenk.github.io
|
||||||
|
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE CPP #-}
|
||||||
|
|
||||||
|
import Text.Pandoc
|
||||||
|
import Text.Pandoc.Walk (walk, query)
|
||||||
|
import Text.Pandoc.Class (runPure)
|
||||||
|
import Text.Pandoc.Builder (text, toList)
|
||||||
|
import Text.Pandoc.Options (def)
|
||||||
|
import Text.Pandoc.JSON (toJSONFilter)
|
||||||
|
|
||||||
|
import Data.Either (fromRight)
|
||||||
|
import Data.List (groupBy)
|
||||||
|
import Data.Tree (Forest, Tree(Node))
|
||||||
|
import Data.Function (on)
|
||||||
|
import Data.Maybe (fromMaybe)
|
||||||
|
import Data.Text (unpack)
|
||||||
|
|
||||||
|
data TOCAlignment = TOCOff | TOCLeft | TOCRight
|
||||||
|
|
||||||
|
headerLevel :: Block -> Int
|
||||||
|
headerLevel (Header level _ _) = level
|
||||||
|
headerLevel _ = error "not a header"
|
||||||
|
|
||||||
|
ignoreTOC :: Block -> Block
|
||||||
|
ignoreTOC (Header level (ident, classes, params) inlines) =
|
||||||
|
Header level (ident, "notoc" : classes, params) inlines
|
||||||
|
ignoreTOC 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)
|
||||||
|
|
||||||
|
markupLink :: Attr -> [Inline] -> Inline
|
||||||
|
markupLink (headerId, _, headerProperties) headerText
|
||||||
|
= let linkText = fromMaybe headerText (fmap (toList . text) $ lookup "toc" headerProperties)
|
||||||
|
in Link nullAttr linkText (("#" ++ headerId), headerId)
|
||||||
|
|
||||||
|
markupHeader :: Tree Block -> [Block]
|
||||||
|
markupHeader n@(Node (Header _ hAttr hText) headers)
|
||||||
|
| headers == [] = [link]
|
||||||
|
| otherwise = [link, markupHeaders headers]
|
||||||
|
where link = Plain [markupLink hAttr hText]
|
||||||
|
markupHeader n = error $ "'markupHeader' should only be passed a 'Node $ Header'\n"
|
||||||
|
++ " saw: " ++ show n
|
||||||
|
|
||||||
|
markupHeaders :: Forest Block -> Block
|
||||||
|
markupHeaders = OrderedList (1, Decimal, Period) . map markupHeader
|
||||||
|
|
||||||
|
createTable :: TOCAlignment -> Forest Block -> Block
|
||||||
|
createTable _ [] = Null
|
||||||
|
createTable alignment headers
|
||||||
|
= let alignAttr = case alignment of
|
||||||
|
TOCRight -> " class=\"right-toc\""
|
||||||
|
_ -> ""
|
||||||
|
navBegin = "<nav id=\"toc\"" ++ alignAttr ++ ">"
|
||||||
|
navEnd = "</nav>"
|
||||||
|
tocDoc = Pandoc nullMeta [Para [Str "Contents"], markupHeaders headers]
|
||||||
|
tocString = unpack . fromRight mempty . runPure . writeHtml5String def $ tocDoc
|
||||||
|
in RawBlock "html" (navBegin ++ "\n" ++ tocString ++ "\n" ++ navEnd)
|
||||||
|
|
||||||
|
generateTOC :: [Block] -> TOCAlignment -> Block -> Block
|
||||||
|
generateTOC headers alignment x@(BulletList (( (( Plain ((Str "toc"):_)):_)):_))
|
||||||
|
= createTable alignment . groupByHierarchy $ headers
|
||||||
|
generateTOC _ _ x = x
|
||||||
|
|
||||||
|
tableOfContents :: TOCAlignment -> Pandoc -> Pandoc
|
||||||
|
tableOfContents alignment ast
|
||||||
|
= let headers = query collectHeaders ast
|
||||||
|
tocGen = case alignment of
|
||||||
|
TOCOff -> walk ignoreTOC
|
||||||
|
_ -> walk (generateTOC headers alignment)
|
||||||
|
in tocGen $ ast
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = toJSONFilter (tableOfContents TOCRight)
|
||||||
Loading…
Reference in New Issue
Block a user