module Shikensu.Contrib ( clearMetadata , clearMetadataDef , clone , copyPropsToMetadata , copyPropsToMetadataDef , exclude , insertMetadata , insertMetadataDef , permalink , permalinkDef , prefixDirname , prefixDirnameDef , rename , renameDef , renameExt , renameExtDef , renderContent , renderContentDef , replaceMetadata , replaceMetadataDef ) where import Data.ByteString (ByteString) import Flow import Shikensu (forkDefinition) import Shikensu.Metadata (transposeToMetadata) import Shikensu.Types import Shikensu.Utilities (cleanPath, compileParentPath, compilePathToRoot) import System.FilePath (FilePath, combine) import qualified Data.HashMap.Strict as HashMap (empty, union) {-| Clear metadata. Replace the current hash map with an empty one. -} clearMetadata :: Dictionary -> Dictionary clearMetadata = fmap (clearMetadataDef) clearMetadataDef :: Definition -> Definition clearMetadataDef def = def { metadata = HashMap.empty } {-| Clone. For each definition that has the given `localPath` (1st argument), make a clone with a new `localPath` (2nd argument), and add that into dictionary just after the matching definition. Example: clone "index.html" "200.html" dictionary -} clone :: FilePath -> FilePath -> Dictionary -> Dictionary clone existingPath newPath dict = let makeNew = \def acc -> if (localPath def) == existingPath then acc ++ [forkDefinition newPath def] else acc in dict ++ (foldr makeNew [] dict) {-| Copy definition properties into the metadata. See the `toJSON` implementation for `Definition` in `Shikensu.Types` to see what properties get put in here. -} copyPropsToMetadata :: Dictionary -> Dictionary copyPropsToMetadata = fmap (copyPropsToMetadataDef) copyPropsToMetadataDef :: Definition -> Definition copyPropsToMetadataDef def = def { metadata = HashMap.union (transposeToMetadata def) (metadata def) } {-| Exclude. Filter out the definitions that have the given `localPath`. -} exclude :: FilePath -> Dictionary -> Dictionary exclude path = filter (\def -> (localPath def) /= path) {-| Insert metadata. Merge the current hash map with another one. -} insertMetadata :: Metadata -> Dictionary -> Dictionary insertMetadata a = fmap (insertMetadataDef a) insertMetadataDef :: Metadata -> Definition -> Definition insertMetadataDef given def = def { metadata = HashMap.union given (metadata def) } {-| Permalink. Append the basename to the dirname, and change the basename to the given string. It will NOT change definitions that already have the new basename. Example: permalink "index" dictionary -} permalink :: String -> Dictionary -> Dictionary permalink a = fmap (permalinkDef a) permalinkDef :: String -> Definition -> Definition permalinkDef newBasename def = if (basename def) /= newBasename then let newDirname = cleanPath $ combine (dirname def) (basename def) in def { basename = newBasename , dirname = newDirname , parentPath = compileParentPath $ newDirname , pathToRoot = compilePathToRoot $ newDirname } else def {-| Prefix dirname. Prefix the dirname of each definition with a given string. -} prefixDirname :: String -> Dictionary -> Dictionary prefixDirname prefix = fmap (prefixDirnameDef prefix) prefixDirnameDef :: String -> Definition -> Definition prefixDirnameDef prefix def = def { dirname = prefix ++ (dirname def) } {-| Rename. Change the `localPath` of the definitions that match a given `localPath`. For example, if you have a definition with the local path `a/b/example.html`: rename "a/b/example.html" "example/index.html" dictionary See `Shikensu.localPath` for more info. -} rename :: FilePath -> FilePath -> Dictionary -> Dictionary rename a b = fmap (renameDef a b) renameDef :: FilePath -> FilePath -> Definition -> Definition renameDef oldPath newPath def = if (localPath def) == oldPath then forkDefinition newPath def else def {-| Rename extension. Example: renameExt ".markdown" ".html" dictionary -- The definitions that had the extname ".markdown" -- now have the extname ".html" -} renameExt :: String -> String -> Dictionary -> Dictionary renameExt a b = fmap (renameExtDef a b) renameExtDef :: String -> String -> Definition -> Definition renameExtDef oldExtname newExtname def = if (extname def) == oldExtname then def { extname = newExtname } else def {-| Render content. Replace the content property by providing a renderer. A renderer is a function with the signature `Definition -> Maybe ByteString`. You can use this to render templates, markdown, etc. -} renderContent :: (Definition -> Maybe ByteString) -> Dictionary -> Dictionary renderContent a = fmap (renderContentDef a) renderContentDef :: (Definition -> Maybe ByteString) -> Definition -> Definition renderContentDef renderer def = def { content = renderer def } {-| Replace metadata. Replace the current hash map with another one. -} replaceMetadata :: Metadata -> Dictionary -> Dictionary replaceMetadata a = fmap (replaceMetadataDef a) replaceMetadataDef :: Metadata -> Definition -> Definition replaceMetadataDef given def = def { metadata = given }