-------------------------------------------------------------------------------- -- | An identifier is a type used to uniquely identify a resource, target... -- -- One can think of an identifier as something similar to a file path. An -- identifier is a path as well, with the different elements in the path -- separated by @/@ characters. Examples of identifiers are: -- -- * @posts/foo.markdown@ -- -- * @index@ -- -- * @error/404@ -- -- The most important difference between an 'Identifier' and a file path is that -- the identifier for an item is not necesserily the file path. -- -- For example, we could have an @index@ identifier, generated by Hakyll. The -- actual file path would be @index.html@, but we identify it using @index@. -- -- @posts/foo.markdown@ could be an identifier of an item that is rendered to -- @posts/foo.html@. In this case, the identifier is the name of the source -- file of the page. -- -- An `Identifier` carries the type of the value it identifies. This basically -- means that an @Identifier (Page String)@ refers to a page. -- -- It is a phantom type parameter, meaning you can safely change this if you -- know what you are doing. You can change the type using the 'castIdentifier' -- function. -- -- If the @a@ type is not known, Hakyll traditionally uses @Identifier ()@. {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} module Hakyll.Core.Identifier ( Identifier , fromFilePath , toFilePath , identifierVersion , setVersion ) where -------------------------------------------------------------------------------- import Control.Applicative ((<$>), (<*>)) import Control.DeepSeq (NFData (..)) import Data.List (intercalate) import System.FilePath (dropTrailingPathSeparator, splitPath) -------------------------------------------------------------------------------- import Data.Binary (Binary (..)) import Data.Typeable (Typeable) import GHC.Exts (IsString, fromString) -------------------------------------------------------------------------------- -- | An identifier used to uniquely identify a value data Identifier = Identifier { identifierVersion :: Maybe String , identifierPath :: String } deriving (Eq, Ord, Typeable) -------------------------------------------------------------------------------- instance Binary Identifier where put (Identifier v p) = put v >> put p get = Identifier <$> get <*> get -------------------------------------------------------------------------------- instance IsString Identifier where fromString = fromFilePath -------------------------------------------------------------------------------- instance NFData Identifier where rnf (Identifier v p) = rnf v `seq` rnf p `seq` () -------------------------------------------------------------------------------- instance Show Identifier where show i = case identifierVersion i of Nothing -> toFilePath i Just v -> toFilePath i ++ " (" ++ v ++ ")" -------------------------------------------------------------------------------- -- | Parse an identifier from a string fromFilePath :: String -> Identifier fromFilePath = Identifier Nothing . intercalate "/" . filter (not . null) . split' where split' = map dropTrailingPathSeparator . splitPath -------------------------------------------------------------------------------- -- | Convert an identifier to a relative 'FilePath' toFilePath :: Identifier -> FilePath toFilePath = identifierPath -------------------------------------------------------------------------------- setVersion :: Maybe String -> Identifier -> Identifier setVersion v i = i {identifierVersion = v}