-------------------------------------------------------------------------------- -- | 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 , castIdentifier ) where -------------------------------------------------------------------------------- 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 newtype Identifier a = Identifier {unIdentifier :: String} deriving (Binary, Eq, NFData, Ord, Typeable) -------------------------------------------------------------------------------- instance Show (Identifier a) where show = toFilePath -------------------------------------------------------------------------------- instance IsString (Identifier a) where fromString = fromFilePath -------------------------------------------------------------------------------- -- | Parse an identifier from a string fromFilePath :: String -> Identifier a fromFilePath = Identifier . intercalate "/" . filter (not . null) . split' where split' = map dropTrailingPathSeparator . splitPath -------------------------------------------------------------------------------- -- | Convert an identifier to a relative 'FilePath' toFilePath :: Identifier a -> FilePath toFilePath = unIdentifier -------------------------------------------------------------------------------- -- | Discard the phantom type parameter of an identifier castIdentifier :: Identifier a -> Identifier b castIdentifier (Identifier x) = Identifier x {-# INLINE castIdentifier #-}