{-# LANGUAGE OverloadedStrings #-} module Processing ( build , htmlPipeline , mdPipeline , codePipeline , simplify ) where import Prelude hiding (readFile, writeFile) import Data.Text.IO (writeFile, readFile) import Data.List (partition) import qualified Data.HashMap.Strict as Map import qualified Data.Text as T import Parse import Pretty import Types build mCss pipes file = let fileName = fileNameFromPath file lang = getLang fileName in do stream <- readFile file encoded <- return $ encode stream mapM_ (\f -> f mCss lang fileName encoded) pipes >> return () htmlPipeline = (\dir css lang path enc -> writeFile ((ensureTrailingSlash dir) ++ path ++ ".html") $ pretty lang css enc) mdPipeline = (\dir css lang path enc -> writeFile ((ensureTrailingSlash dir) ++ path ++ ".md") $ (mark lang) enc) codePipeline = (\dir css lang path enc -> writeFile ((ensureTrailingSlash dir) ++ path) $ T.strip $ expand $ merge enc) ensureTrailingSlash dir = if last dir == '/' then dir else dir ++ "/" -- merge together definitions with the same name merge :: [Chunk] -> [Chunk] merge chunks = mergeAux [] (filter isDef chunks) mergeAux ans [] = ans mergeAux ans (next:rest) = let name = getName next (found, rem) = partition (sameName name) rest merged = combineChunks (next:found) in mergeAux (merged:ans) rem -- many consecutive Proses are reduced to a single Prose simplify :: [Chunk] -> [Chunk] simplify [] = [] simplify lst = let (defs, ps) = span isDef lst (ps', rest) = break isDef ps in case ps' of [] -> defs ++ rest _ -> defs ++ [mergeProse ps'] ++ (simplify rest) mergeProse :: [Chunk] -> Chunk mergeProse lst = Prose $ T.concat $ map getProseText lst consecutive :: [Chunk] -> ([Chunk],[Chunk]) consecutive [] = ([],[]) consecutive lst@(fst:rest) = case fst of Prose _ -> break isDef lst Def _ _ _ -> span isDef lst -- assumes always one or more chunk combineChunks :: [Chunk] -> Chunk combineChunks (a:[]) = a combineChunks l@(c:cs) = Def line name parts where parts = concatMap getParts l name = getName c line = getLineNo c isDef chunk = case chunk of Def _ _ _ -> True Prose _ -> False getProseText prose = case prose of Prose txt -> txt _ -> error "cannot retrieve txt, not a prose" getName chunk = case chunk of Def _ name _ -> name _ -> error "cannot retrieve name, not a chunk" getParts chunk = case chunk of Def _ _ parts -> parts _ -> error "cannot retrieve parts, not a chunk" getLineNo chunk = case chunk of Def line _ _ -> line _ -> error "cannot retrieve line number, not a chunk" sameName name chunk = name == (getName chunk) expand :: [Chunk] -> T.Text expand chunks = let -- map (name, parts) partMap = Map.fromList $ zip (map getName chunks) (map getParts chunks) rootParts = Map.lookupDefault [] "*" partMap in expandParts rootParts partMap expandParts :: [Part] -> Map.HashMap T.Text [Part] -> T.Text expandParts parts partMap = let toText = (\part -> case part of Code txt -> txt Ref name -> expandParts refParts partMap where refParts = Map.lookupDefault [] (T.strip name) partMap) in T.concat (map toText parts)