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