hakyllbars-1.0.1.0: A Hakyll compiler for Handlebars-like templates
Safe HaskellSafe-Inferred
LanguageHaskell2010

Hakyllbars.Common

Synopsis

Documentation

(<|>) :: Alternative f => f a -> f a -> f a infixl 3 #

An associative binary operation

bracket #

Arguments

:: IO a

computation to run first ("acquire resource")

-> (a -> IO b)

computation to run last ("release resource")

-> (a -> IO c)

computation to run in-between

-> IO c 

When you want to acquire a resource, do some work with it, and then release the resource, it is a good idea to use bracket, because bracket will install the necessary exception handler to release the resource in the event that an exception is raised during the computation. If an exception is raised, then bracket will re-raise the exception (after performing the release).

A common example is opening a file:

bracket
  (openFile "filename" ReadMode)
  (hClose)
  (\fileHandle -> do { ... })

The arguments to bracket are in this order so that we can partially apply it, e.g.:

withFile name mode = bracket (openFile name mode) hClose

Bracket wraps the release action with mask, which is sufficient to ensure that the release action executes to completion when it does not invoke any interruptible actions, even in the presence of asynchronous exceptions. For example, hClose is uninterruptible when it is not racing other uses of the handle. Similarly, closing a socket (from "network" package) is also uninterruptible under similar conditions. An example of an interruptible action is killThread. Completion of interruptible release actions can be ensured by wrapping them in in uninterruptibleMask_, but this risks making the program non-responsive to Control-C, or timeouts. Another option is to run the release action asynchronously in its own thread:

void $ uninterruptibleMask_ $ forkIO $ do { ... }

The resource will be released as soon as possible, but the thread that invoked bracket will not block in an uninterruptible state.

join :: Monad m => m (m a) -> m a #

The join function is the conventional monad join operator. It is used to remove one level of monadic structure, projecting its bound argument into the outer level.

'join bss' can be understood as the do expression

do bs <- bss
   bs

Examples

Expand

A common use of join is to run an IO computation returned from an STM transaction, since STM transactions can't perform IO directly. Recall that

atomically :: STM a -> IO a

is used to run STM transactions atomically. So, by specializing the types of atomically and join to

atomically :: STM (IO b) -> IO (IO b)
join       :: IO (IO b)  -> IO b

we can compose them as

join . atomically :: STM (IO b) -> IO b

to run an STM transaction and the IO action it returns.

void :: Functor f => f a -> f () #

void value discards or ignores the result of evaluation, such as the return value of an IO action.

Examples

Expand

Replace the contents of a Maybe Int with unit:

>>> void Nothing
Nothing
>>> void (Just 3)
Just ()

Replace the contents of an Either Int Int with unit, resulting in an Either Int ():

>>> void (Left 8675309)
Left 8675309
>>> void (Right 8675309)
Right ()

Replace every element of a list with unit:

>>> void [1,2,3]
[(),(),()]

Replace the second element of a pair with unit:

>>> void (1,2)
(1,())

Discard the result of an IO action:

>>> mapM print [1,2]
1
2
[(),()]
>>> void $ mapM print [1,2]
1
2

(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c infixr 1 #

Left-to-right composition of Kleisli arrows.

'(bs >=> cs) a' can be understood as the do expression

do b <- bs a
   cs b

(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c infixr 1 #

Right-to-left composition of Kleisli arrows. (>=>), with the arguments flipped.

Note how this operator resembles function composition (.):

(.)   ::            (b ->   c) -> (a ->   b) -> a ->   c
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c

forM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b) #

forM is mapM with its arguments flipped. For a version that ignores the results see forM_.

class Monad m => MonadError e (m :: Type -> Type) | m -> e where #

The strategy of combining computations that can throw exceptions by bypassing bound functions from the point an exception is thrown to the point that it is handled.

Is parameterized over the type of error information and the monad type constructor. It is common to use Either String as the monad type constructor for an error monad in which error descriptions take the form of strings. In that case and many other common cases the resulting monad is already defined as an instance of the MonadError class. You can also define your own error type and/or use a monad type constructor other than Either String or Either IOError. In these cases you will have to explicitly define instances of the MonadError class. (If you are using the deprecated Control.Monad.Error or Control.Monad.Trans.Error, you may also have to define an Error instance.)

Methods

throwError :: e -> m a #

Is used within a monadic computation to begin exception processing.

catchError :: m a -> (e -> m a) -> m a #

A handler function to handle previous errors and return to normal execution. A common idiom is:

do { action1; action2; action3 } `catchError` handler

where the action functions can call throwError. Note that handler and the do-block must have the same return type.

Instances

Instances details
MonadError IOException IO 
Instance details

Defined in Control.Monad.Error.Class

Methods

throwError :: IOException -> IO a #

catchError :: IO a -> (IOException -> IO a) -> IO a #

MonadError PandocError PandocIO 
Instance details

Defined in Text.Pandoc.Class.PandocIO

MonadError PandocError PandocPure 
Instance details

Defined in Text.Pandoc.Class.PandocPure

MonadError () Maybe

Since: mtl-2.2.2

Instance details

Defined in Control.Monad.Error.Class

Methods

throwError :: () -> Maybe a #

catchError :: Maybe a -> (() -> Maybe a) -> Maybe a #

MonadError e (Either e) 
Instance details

Defined in Control.Monad.Error.Class

Methods

throwError :: e -> Either e a #

catchError :: Either e a -> (e -> Either e a) -> Either e a #

MonadError e m => MonadError e (ResourceT m) 
Instance details

Defined in Control.Monad.Trans.Resource.Internal

Methods

throwError :: e -> ResourceT m a #

catchError :: ResourceT m a -> (e -> ResourceT m a) -> ResourceT m a #

MonadError e m => MonadError e (ListT m) 
Instance details

Defined in Control.Monad.Error.Class

Methods

throwError :: e -> ListT m a #

catchError :: ListT m a -> (e -> ListT m a) -> ListT m a #

MonadError e m => MonadError e (MaybeT m) 
Instance details

Defined in Control.Monad.Error.Class

Methods

throwError :: e -> MaybeT m a #

catchError :: MaybeT m a -> (e -> MaybeT m a) -> MaybeT m a #

(Monad m, Error e) => MonadError e (ErrorT e m) 
Instance details

Defined in Control.Monad.Error.Class

Methods

throwError :: e -> ErrorT e m a #

catchError :: ErrorT e m a -> (e -> ErrorT e m a) -> ErrorT e m a #

Monad m => MonadError e (ExceptT e m)

Since: mtl-2.2

Instance details

Defined in Control.Monad.Error.Class

Methods

throwError :: e -> ExceptT e m a #

catchError :: ExceptT e m a -> (e -> ExceptT e m a) -> ExceptT e m a #

MonadError e m => MonadError e (IdentityT m) 
Instance details

Defined in Control.Monad.Error.Class

Methods

throwError :: e -> IdentityT m a #

catchError :: IdentityT m a -> (e -> IdentityT m a) -> IdentityT m a #

MonadError e m => MonadError e (ReaderT r m) 
Instance details

Defined in Control.Monad.Error.Class

Methods

throwError :: e -> ReaderT r m a #

catchError :: ReaderT r m a -> (e -> ReaderT r m a) -> ReaderT r m a #

MonadError e m => MonadError e (StateT s m) 
Instance details

Defined in Control.Monad.Error.Class

Methods

throwError :: e -> StateT s m a #

catchError :: StateT s m a -> (e -> StateT s m a) -> StateT s m a #

MonadError e m => MonadError e (StateT s m) 
Instance details

Defined in Control.Monad.Error.Class

Methods

throwError :: e -> StateT s m a #

catchError :: StateT s m a -> (e -> StateT s m a) -> StateT s m a #

(Monoid w, MonadError e m) => MonadError e (WriterT w m) 
Instance details

Defined in Control.Monad.Error.Class

Methods

throwError :: e -> WriterT w m a #

catchError :: WriterT w m a -> (e -> WriterT w m a) -> WriterT w m a #

(Monoid w, MonadError e m) => MonadError e (WriterT w m) 
Instance details

Defined in Control.Monad.Error.Class

Methods

throwError :: e -> WriterT w m a #

catchError :: WriterT w m a -> (e -> WriterT w m a) -> WriterT w m a #

MonadError e m => MonadError e (ConduitT i o m) 
Instance details

Defined in Data.Conduit.Internal.Conduit

Methods

throwError :: e -> ConduitT i o m a #

catchError :: ConduitT i o m a -> (e -> ConduitT i o m a) -> ConduitT i o m a #

MonadError e m => MonadError e (ParsecT s u m) 
Instance details

Defined in Text.Parsec.Prim

Methods

throwError :: e -> ParsecT s u m a #

catchError :: ParsecT s u m a -> (e -> ParsecT s u m a) -> ParsecT s u m a #

(Monoid w, MonadError e m) => MonadError e (RWST r w s m) 
Instance details

Defined in Control.Monad.Error.Class

Methods

throwError :: e -> RWST r w s m a #

catchError :: RWST r w s m a -> (e -> RWST r w s m a) -> RWST r w s m a #

(Monoid w, MonadError e m) => MonadError e (RWST r w s m) 
Instance details

Defined in Control.Monad.Error.Class

Methods

throwError :: e -> RWST r w s m a #

catchError :: RWST r w s m a -> (e -> RWST r w s m a) -> RWST r w s m a #

MonadError e m => MonadError e (Pipe l i o u m) 
Instance details

Defined in Data.Conduit.Internal.Pipe

Methods

throwError :: e -> Pipe l i o u m a #

catchError :: Pipe l i o u m a -> (e -> Pipe l i o u m a) -> Pipe l i o u m a #

MonadError [String] Compiler

Compilation may fail with multiple error messages. catchError handles errors from throwError, fail and noResult

Instance details

Defined in Hakyll.Core.Compiler.Internal

Methods

throwError :: [String] -> Compiler a #

catchError :: Compiler a -> ([String] -> Compiler a) -> Compiler a #

lift :: (MonadTrans t, Monad m) => m a -> t m a #

Lift a computation from the argument monad to the constructed monad.

second :: Bifunctor p => (b -> c) -> p a b -> p a c #

Map covariantly over the second argument.

secondbimap id

Examples

Expand
>>> second (+1) ('j', 3)
('j',4)
>>> second (+1) (Right 3)
Right 4

bimap :: Bifunctor p => (a -> b) -> (c -> d) -> p a c -> p b d #

Map over both arguments at the same time.

bimap f g ≡ first f . second g

Examples

Expand
>>> bimap toUpper (+1) ('j', 3)
('J',4)
>>> bimap toUpper (+1) (Left 'j')
Left 'J'
>>> bimap toUpper (+1) (Right 3)
Right 4

first :: Bifunctor p => (a -> b) -> p a c -> p b c #

Map covariantly over the first argument.

first f ≡ bimap f id

Examples

Expand
>>> first toUpper ('j', 3)
('J',3)
>>> first toUpper (Left 'j')
Left 'J'

bool :: a -> a -> Bool -> a #

Case analysis for the Bool type. bool x y p evaluates to x when p is False, and evaluates to y when p is True.

This is equivalent to if p then y else x; that is, one can think of it as an if-then-else construct with its arguments reordered.

Examples

Expand

Basic usage:

>>> bool "foo" "bar" True
"bar"
>>> bool "foo" "bar" False
"foo"

Confirm that bool x y p and if p then y else x are equivalent:

>>> let p = True; x = "bar"; y = "foo"
>>> bool x y p == if p then y else x
True
>>> let p = False
>>> bool x y p == if p then y else x
True

Since: base-4.7.0.0

sequenceA_ :: (Foldable t, Applicative f) => t (f a) -> f () #

Evaluate each action in the structure from left to right, and ignore the results. For a version that doesn't ignore the results see sequenceA.

sequenceA_ is just like sequence_, but generalised to Applicative actions.

Examples

Expand

Basic usage:

>>> sequenceA_ [print "Hello", print "world", print "!"]
"Hello"
"world"
"!"

(<&>) :: Functor f => f a -> (a -> b) -> f b infixl 1 #

Flipped version of <$>.

(<&>) = flip fmap

Examples

Expand

Apply (+1) to a list, a Just and a Right:

>>> Just 2 <&> (+1)
Just 3
>>> [1,2,3] <&> (+1)
[2,3,4]
>>> Right 3 <&> (+1)
Right 4

Since: base-4.11.0.0

intercalate :: [a] -> [[a]] -> [a] #

intercalate xs xss is equivalent to (concat (intersperse xs xss)). It inserts the list xs in between the lists in xss and concatenates the result.

>>> intercalate ", " ["Lorem", "ipsum", "dolor"]
"Lorem, ipsum, dolor"

isSuffixOf :: Eq a => [a] -> [a] -> Bool #

The isSuffixOf function takes two lists and returns True iff the first list is a suffix of the second. The second list must be finite.

>>> "ld!" `isSuffixOf` "Hello World!"
True
>>> "World" `isSuffixOf` "Hello World!"
False

isPrefixOf :: Eq a => [a] -> [a] -> Bool #

\(\mathcal{O}(\min(m,n))\). The isPrefixOf function takes two lists and returns True iff the first list is a prefix of the second.

>>> "Hello" `isPrefixOf` "Hello World!"
True
>>> "Hello" `isPrefixOf` "Wello Horld!"
False

fromJust :: HasCallStack => Maybe a -> a #

The fromJust function extracts the element out of a Just and throws an error if its argument is Nothing.

Examples

Expand

Basic usage:

>>> fromJust (Just 1)
1
>>> 2 * (fromJust (Just 10))
20
>>> 2 * (fromJust Nothing)
*** Exception: Maybe.fromJust: Nothing
...

fromMaybe :: a -> Maybe a -> a #

The fromMaybe function takes a default value and a Maybe value. If the Maybe is Nothing, it returns the default value; otherwise, it returns the value contained in the Maybe.

Examples

Expand

Basic usage:

>>> fromMaybe "" (Just "Hello, World!")
"Hello, World!"
>>> fromMaybe "" Nothing
""

Read an integer from a string using readMaybe. If we fail to parse an integer, we want to return 0 by default:

>>> import Text.Read ( readMaybe )
>>> fromMaybe 0 (readMaybe "5")
5
>>> fromMaybe 0 (readMaybe "")
0

maybeToList :: Maybe a -> [a] #

The maybeToList function returns an empty list when given Nothing or a singleton list when given Just.

Examples

Expand

Basic usage:

>>> maybeToList (Just 7)
[7]
>>> maybeToList Nothing
[]

One can use maybeToList to avoid pattern matching when combined with a function that (safely) works on lists:

>>> import Text.Read ( readMaybe )
>>> sum $ maybeToList (readMaybe "3")
3
>>> sum $ maybeToList (readMaybe "")
0

maybe :: b -> (a -> b) -> Maybe a -> b #

The maybe function takes a default value, a function, and a Maybe value. If the Maybe value is Nothing, the function returns the default value. Otherwise, it applies the function to the value inside the Just and returns the result.

Examples

Expand

Basic usage:

>>> maybe False odd (Just 3)
True
>>> maybe False odd Nothing
False

Read an integer from a string using readMaybe. If we succeed, return twice the integer; that is, apply (*2) to it. If instead we fail to parse an integer, return 0 by default:

>>> import Text.Read ( readMaybe )
>>> maybe 0 (*2) (readMaybe "5")
10
>>> maybe 0 (*2) (readMaybe "")
0

Apply show to a Maybe Int. If we have Just n, we want to show the underlying Int n. But if we have Nothing, we return the empty string instead of (for example) "Nothing":

>>> maybe "" show (Just 5)
"5"
>>> maybe "" show Nothing
""

isNothing :: Maybe a -> Bool #

The isNothing function returns True iff its argument is Nothing.

Examples

Expand

Basic usage:

>>> isNothing (Just 3)
False
>>> isNothing (Just ())
False
>>> isNothing Nothing
True

Only the outer constructor is taken into consideration:

>>> isNothing (Just Nothing)
False

isJust :: Maybe a -> Bool #

The isJust function returns True iff its argument is of the form Just _.

Examples

Expand

Basic usage:

>>> isJust (Just 3)
True
>>> isJust (Just ())
True
>>> isJust Nothing
False

Only the outer constructor is taken into consideration:

>>> isJust (Just Nothing)
True

data ZonedTime #

A local time together with a time zone.

There is no Eq instance for ZonedTime. If you want to compare local times, use zonedTimeToLocalTime. If you want to compare absolute times, use zonedTimeToUTC.

Instances

Instances details
FromJSON ZonedTime

Supported string formats:

YYYY-MM-DD HH:MMZ YYYY-MM-DD HH:MM:SSZ YYYY-MM-DD HH:MM:SS.SSSZ

The first space may instead be a T, and the second space is optional. The Z represents UTC. The Z may be replaced with a time zone offset of the form +0000 or -08:00, where the first two digits are hours, the : is optional and the second two digits (also optional) are minutes.

Instance details

Defined in Data.Aeson.Types.FromJSON

FromJSONKey ZonedTime 
Instance details

Defined in Data.Aeson.Types.FromJSON

ToJSON ZonedTime 
Instance details

Defined in Data.Aeson.Types.ToJSON

ToJSONKey ZonedTime 
Instance details

Defined in Data.Aeson.Types.ToJSON

Data ZonedTime 
Instance details

Defined in Data.Time.LocalTime.Internal.ZonedTime

Methods

gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> ZonedTime -> c ZonedTime #

gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c ZonedTime #

toConstr :: ZonedTime -> Constr #

dataTypeOf :: ZonedTime -> DataType #

dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c ZonedTime) #

dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ZonedTime) #

gmapT :: (forall b. Data b => b -> b) -> ZonedTime -> ZonedTime #

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> ZonedTime -> r #

gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> ZonedTime -> r #

gmapQ :: (forall d. Data d => d -> u) -> ZonedTime -> [u] #

gmapQi :: Int -> (forall d. Data d => d -> u) -> ZonedTime -> u #

gmapM :: Monad m => (forall d. Data d => d -> m d) -> ZonedTime -> m ZonedTime #

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> ZonedTime -> m ZonedTime #

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> ZonedTime -> m ZonedTime #

Show ZonedTime

For the time zone, this only shows the name, or offset if the name is empty.

Instance details

Defined in Data.Time.LocalTime.Internal.ZonedTime

NFData ZonedTime 
Instance details

Defined in Data.Time.LocalTime.Internal.ZonedTime

Methods

rnf :: ZonedTime -> () #

formatTime :: FormatTime t => TimeLocale -> String -> t -> String #

Substitute various time-related information for each %-code in the string, as per formatCharacter.

The general form is %<modifier><width><alternate><specifier>, where <modifier>, <width>, and <alternate> are optional.

<modifier>

glibc-style modifiers can be used before the specifier (here marked as z):

%-z
no padding
%_z
pad with spaces
%0z
pad with zeros
%^z
convert to upper case
%#z
convert to lower case (consistently, unlike glibc)

<width>

Width digits can also be used after any modifiers and before the specifier (here marked as z), for example:

%4z
pad to 4 characters (with default padding character)
%_12z
pad with spaces to 12 characters

<alternate>

An optional E character indicates an alternate formatting. Currently this only affects %Z and %z.

%Ez
alternate formatting

<specifier>

For all types (note these three are done by formatTime, not by formatCharacter):

%%
%
%t
tab
%n
newline

TimeZone

For TimeZone (and ZonedTime and UTCTime):

%z
timezone offset in the format ±HHMM
%Ez
timezone offset in the format ±HH:MM
%Z
timezone name (or else offset in the format ±HHMM)
%EZ
timezone name (or else offset in the format ±HH:MM)

LocalTime

For LocalTime (and ZonedTime and UTCTime and UniversalTime):

%c
as dateTimeFmt locale (e.g. %a %b %e %H:%M:%S %Z %Y)

TimeOfDay

For TimeOfDay (and LocalTime and ZonedTime and UTCTime and UniversalTime):

%R
same as %H:%M
%T
same as %H:%M:%S
%X
as timeFmt locale (e.g. %H:%M:%S)
%r
as time12Fmt locale (e.g. %I:%M:%S %p)
%P
day-half of day from (amPm locale), converted to lowercase, am, pm
%p
day-half of day from (amPm locale), AM, PM
%H
hour of day (24-hour), 0-padded to two chars, 00 - 23
%k
hour of day (24-hour), space-padded to two chars, 0 - 23
%I
hour of day-half (12-hour), 0-padded to two chars, 01 - 12
%l
hour of day-half (12-hour), space-padded to two chars, 1 - 12
%M
minute of hour, 0-padded to two chars, 00 - 59
%S
second of minute (without decimal part), 0-padded to two chars, 00 - 60
%q
picosecond of second, 0-padded to twelve chars, 000000000000 - 999999999999.
%Q
decimal point and fraction of second, up to 12 second decimals, without trailing zeros. For a whole number of seconds, %Q omits the decimal point unless padding is specified.

UTCTime and ZonedTime

For UTCTime and ZonedTime:

%s
number of whole seconds since the Unix epoch. For times before the Unix epoch, this is a negative number. Note that in %s.%q and %s%Q the decimals are positive, not negative. For example, 0.9 seconds before the Unix epoch is formatted as -1.1 with %s%Q.

DayOfWeek

For DayOfWeek (and Day and LocalTime and ZonedTime and UTCTime and UniversalTime):

%u
day of week number for Week Date format, 1 (= Monday) - 7 (= Sunday)
%w
day of week number, 0 (= Sunday) - 6 (= Saturday)
%a
day of week, short form (snd from wDays locale), Sun - Sat
%A
day of week, long form (fst from wDays locale), Sunday - Saturday

Month

For Month (and Day and LocalTime and ZonedTime and UTCTime and UniversalTime):

%Y
year, no padding. Note %0Y and %_Y pad to four chars
%y
year of century, 0-padded to two chars, 00 - 99
%C
century, no padding. Note %0C and %_C pad to two chars
%B
month name, long form (fst from months locale), January - December
%b, %h
month name, short form (snd from months locale), Jan - Dec
%m
month of year, 0-padded to two chars, 01 - 12

Day

For Day (and LocalTime and ZonedTime and UTCTime and UniversalTime):

%D
same as %m/%d/%y
%F
same as %Y-%m-%d
%x
as dateFmt locale (e.g. %m/%d/%y)
%d
day of month, 0-padded to two chars, 01 - 31
%e
day of month, space-padded to two chars, 1 - 31
%j
day of year, 0-padded to three chars, 001 - 366
%f
century for Week Date format, no padding. Note %0f and %_f pad to two chars
%V
week of year for Week Date format, 0-padded to two chars, 01 - 53
%U
week of year where weeks start on Sunday (as sundayStartWeek), 0-padded to two chars, 00 - 53
%W
week of year where weeks start on Monday (as mondayStartWeek), 0-padded to two chars, 00 - 53

Duration types

The specifiers for DiffTime, NominalDiffTime, CalendarDiffDays, and CalendarDiffTime are semantically separate from the other types. Specifiers on negative time differences will generally be negative (think rem rather than mod).

NominalDiffTime and DiffTime

Note that a "minute" of DiffTime is simply 60 SI seconds, rather than a minute of civil time. Use NominalDiffTime to work with civil time, ignoring any leap seconds.

For NominalDiffTime and DiffTime:

%w
total whole weeks
%d
total whole days
%D
whole days of week
%h
total whole hours
%H
whole hours of day
%m
total whole minutes
%M
whole minutes of hour
%s
total whole seconds
%Es
total seconds, with decimal point and up to <width> (default 12) decimal places, without trailing zeros. For a whole number of seconds, %Es omits the decimal point unless padding is specified.
%0Es
total seconds, with decimal point and <width> (default 12) decimal places.
%S
whole seconds of minute
%ES
seconds of minute, with decimal point and up to <width> (default 12) decimal places, without trailing zeros. For a whole number of seconds, %ES omits the decimal point unless padding is specified.
%0ES
seconds of minute as two digits, with decimal point and <width> (default 12) decimal places.

CalendarDiffDays

For CalendarDiffDays (and CalendarDiffTime):

%y
total years
%b
total months
%B
months of year
%w
total weeks, not including months
%d
total days, not including months
%D
days of week

CalendarDiffTime

For CalendarDiffTime:

%h
total hours, not including months
%H
hours of day
%m
total minutes, not including months
%M
minutes of hour
%s
total whole seconds, not including months
%Es
total seconds, not including months, with decimal point and up to <width> (default 12) decimal places, without trailing zeros. For a whole number of seconds, %Es omits the decimal point unless padding is specified.
%0Es
total seconds, not including months, with decimal point and <width> (default 12) decimal places.
%S
whole seconds of minute
%ES
seconds of minute, with decimal point and up to <width> (default 12) decimal places, without trailing zeros. For a whole number of seconds, %ES omits the decimal point unless padding is specified.
%0ES
seconds of minute as two digits, with decimal point and <width> (default 12) decimal places.

parseTimeM #

Arguments

:: (MonadFail m, ParseTime t) 
=> Bool

Accept leading and trailing whitespace?

-> TimeLocale

Time locale.

-> String

Format string.

-> String

Input string.

-> m t

Return the time value, or fail if the input could not be parsed using the given format.

Parses a time value given a format string. Missing information will be derived from 1970-01-01 00:00 UTC (which was a Thursday). Supports the same %-codes as formatTime, including %-, %_ and %0 modifiers, however padding widths are not supported. Case is not significant in the input string. Some variations in the input are accepted:

%z %Ez
accepts any of ±HHMM or ±HH:MM.
%Z %EZ
accepts any string of letters, or any of the formats accepted by %z.
%0Y
accepts exactly four digits.
%0G
accepts exactly four digits.
%0C
accepts exactly two digits.
%0f
accepts exactly two digits.

For example, to parse a date in YYYY-MM-DD format, while allowing the month and date to have optional leading zeros (notice the - modifier used for %m and %d):

Prelude Data.Time> parseTimeM True defaultTimeLocale "%Y-%-m-%-d" "2010-3-04" :: Maybe Day
Just 2010-03-04

data FeedConfiguration #

This is a data structure to keep the configuration of a feed.

Constructors

FeedConfiguration 

Fields

data Redirect #

This datatype can be used directly if you want a lower-level interface to generate redirects. For example, if you want to redirect foo.html to bar.jpg, you can use:

create ["foo.html"] $ do
    route idRoute
    compile $ makeItem $ Redirect "bar.jpg"

Constructors

Redirect 

Fields

Instances

Instances details
Show Redirect 
Instance details

Defined in Hakyll.Web.Redirect

Binary Redirect 
Instance details

Defined in Hakyll.Web.Redirect

Methods

put :: Redirect -> Put #

get :: Get Redirect #

putList :: [Redirect] -> Put #

Eq Redirect 
Instance details

Defined in Hakyll.Web.Redirect

Ord Redirect 
Instance details

Defined in Hakyll.Web.Redirect

Writable Redirect 
Instance details

Defined in Hakyll.Web.Redirect

Methods

write :: FilePath -> Item Redirect -> IO () #

relativizeUrls :: Item String -> Compiler (Item String) #

Compiler form of relativizeUrls which automatically picks the right root path

escapeHtml :: String -> String #

HTML-escape a string

Example:

escapeHtml "Me & Dean"

Result:

"Me &amp; Dean"

toUrl :: FilePath -> String #

Convert a filepath to an URL starting from the site root

Example:

toUrl "foo/bar.html"

Result:

"/foo/bar.html"

This also sanitizes the URL, e.g. converting spaces into '%20'

rulesExtraDependencies :: [Dependency] -> Rules a -> Rules a #

Advanced usage: add extra dependencies to compilers. Basically this is needed when you're doing unsafe tricky stuff in the rules monad, but you still want correct builds.

A useful utility for this purpose is makePatternDependency.

route #

Arguments

:: Routes

Where to output compilation results

-> Rules ()

Result

Add (or replace) routing in the current Rules value. This functions controls IF and WHERE the compiled results are written out (use one of the match functions to control WHAT content is processed and compile to control HOW). See Routes and Identifier for details on how output filepaths are computed.

Hint: If there's no route attached to a rule, the compilation result is not written out. However, the compilation result is saved to the Store and can be loaded and used within another rule. This behavior is needed, for example, for templates.

Examples

Expand

Rules with and without routing

-- e.g. file on disk: 'templates/post.html'

-- Rule 1 (without routing)
match "templates/*" $ do
    -- compilation result saved to store with implicit identifier, e.g. 'templates/post.html'
    compile templateCompiler

-- Rule 2 (with routing)
match "posts/**.md" $ do
    route $ setExtension "html"
    compile $ do
       -- load compiled result of other rule with explicit identifier.
       postTemplate <- loadBody "templates/post.html"
       pandocCompiler >>= applyTemplate postTemplate defaultContext

Note that we don't set a route in the first rule to avoid writing out our compiled templates. However, we can still load (or loadBody) the compiled templates to apply them in a second rule. The content for templateCompiler comes implicitly from the matched template files on disk. We don't have to pass that content around manually. See match and compile for details.

To control where a compilation result will be written out (as done in the second rule), use routing functions like setExtension.

See Hakyll.Web.Template for examples of templates and the templating syntax.

compile #

Arguments

:: (Binary a, Typeable a, Writable a) 
=> Compiler (Item a)

How to transform content

-> Rules ()

Result

Add (or replace) the given compilation steps within the given Compiler value to the current Rules value. This functions controls HOW the content within a rule is processed (use one of the match functions to control WHAT content is processed).

The compilation result is saved to the Store under an implicit identifier. See Identifier for details.

If there's routing attached to the rule where this function is used, the compilation result is also written out to a file according to that route. See route and Routes for details.

Examples

Expand

Compile Markdown to HTML

-- Select all Markdown files in 'posts' directory
match "posts/**.md" $ do

    route $ setExtension "html"

    -- use pandoc to transform Markdown to HTML in a single step
    compile pandocCompiler

Note how we set the content to be processed with pandocCompiler. The content comes implicitly from the matched Markdown files on disk. We don't have to pass that content around manually. Every file is processed the same way within this one rule.

To control where the compilation result will be written out, use routing functions like setExtension. Here the compilation result of a file like posts/hakyll.md is written out to posts/hakyll.html.

Compile Markdown to HTML and embed it in a template

-- Select all Markdown files in 'posts' directory
match "posts/**.md" $ do
    route $ setExtension "html"
    compile $
        pandocCompiler >>=
          loadAndApplyTemplate "templates/post.html" defaultContext

-- To Hakyll templates are just plain files that have to be processed
-- and placed into the store like any other file (but without routing).
-- e.g. file on disk: 'templates/post.html'
match "templates/*" $ compile templateBodyCompiler

Note how a Markdown post that is compiled to HTML using pandocCompiler in a first step and then embedded into a HTMl Template in a second step by using loadAndApplyTemplate. We can use templates to control the design and layout of a webpage. A template may look as follows:

<h1>$title$</h1>
$body$

See Hakyll.Web.Template to see examples of the templating syntax.

version #

Arguments

:: String

Version name to add

-> Rules ()

Remaining processing parts

-> Rules ()

Result

Add the given version name to the implicit identifier(s) under which the compilation result of the given remaining Rules value is saved to the Store. See Identifier for details.

Use this wrapper function for example when you need to compile the same source file into two or more different results, each with a different version name. The version is needed to distinguish between these different compilation results in the store, otherwise they would get the same conflicting identifier in the store.

Warning: If you add a version name with this function, you need to supply the same name when you load the content from the store from within another rule.

Examples

Expand

Compile source file into differently versioned outputs and load both

-- e.g. file on disk: 'posts/hakyll.md'

-- saved with implicit identifier ('posts/hakyll.md', no-version)
match "posts/*" $ do
    route $ setExtension "html"
    compile pandocCompiler

-- saved with implicit identifier ('posts/hakyll.md', version 'raw')
match "posts/*" $ version "raw" $ do
    route idRoute
    compile getResourceBody

-- use compilation results from rules above
create ["index.html"] $ do
    route idRoute
    compile $ do
        -- load no-version version
        compiledPost <- load (fromFilePath "posts/hakyll.md")
        -- load version 'raw'
        rawPost <- load . setVersion (Just "raw") $ fromFilePath "posts/hakyll.md"
        ...

Note how a version name is needed to distinguish the unversioned and the "raw" version when loading the Hakyll post for the index.html page. To control where the compilation result will be written out, use routing functions like idRoute and setExtension.

create #

Arguments

:: [Identifier]

Identifiers to assign to created content in next argument

-> Rules ()

Remaining processing parts that must create content

-> Rules ()

Resulting rule

Assign (and thereby create) the given identifier(s) to content that has no underlying source file on disk. That content must be created within the compile part of the given remaining Rules value. The given identifier is the id under which the compilation is saved to the Store (in case you want to load it within another rule). See Identifier for details.

Use this function for example to create an overview page that doesn't have or need its content prepared in a file (unlike blog posts which normally have a corresponding Markdown source file on disk).

Examples

Expand

Create a webpage without an underlying source file

-- saved with implicit identifier 'index.html' to Store
create ["index.html"] $ do

    -- compilation result is written to '<destination-directory>/index.html'
    route idRoute

    -- create content without a source file from disk
    compile $ makeItem ("<h1>Hello World</h1>" :: String)

Note how you can use makeItem to create content inline (to be processed as a Compiler value) as if that content was loaded from a file (as it's the case when using match). To control where the compilation result will be written out, use routing functions like idRoute.

match #

Arguments

:: Pattern

Glob pattern

-> Rules ()

Remaining processing parts

-> Rules ()

Result

Add a selection of which source files to process (using the given glob pattern) to the given remaining Rules value.

The expanded, relative path of the matched source file on disk (relative to the project directory configured with providerDirectory) becomes the identifier under which the compilation result is saved to the Store (in case you want to load it within another rule). See Identifier for details.

Examples

Expand

Select all markdown files within a directory (but without subdirectories)

-- Match all Markdown files in the immediate 'posts' directory
-- e.g. '<project-directory>/posts/hakyll.md'
-- but NOT  '<project-directory>/posts/haskell/monad.md'
match "posts/*.md" $ do
    route $ setExtension "html"
    compile pandocCompiler

Select all markdown files within a directory (including subdirectories recursively)

-- Match all Markdown files in the 'posts' directory and any subdirectory
-- e.g. '<project-directory>/posts/hakyll.md'
-- and  '<project-directory>/posts/haskell/monad.md'
match "posts/**.md" $ do
    route $ setExtension "html"
    compile pandocCompiler

See Pattern or search "glob patterns" online for more details. To control where the compilation result will be written out, use routing functions like setExtension.

data Rules a #

The monad used to compose rules

Instances

Instances details
MonadFail Rules 
Instance details

Defined in Hakyll.Core.Rules.Internal

Methods

fail :: String -> Rules a #

Applicative Rules 
Instance details

Defined in Hakyll.Core.Rules.Internal

Methods

pure :: a -> Rules a #

(<*>) :: Rules (a -> b) -> Rules a -> Rules b #

liftA2 :: (a -> b -> c) -> Rules a -> Rules b -> Rules c #

(*>) :: Rules a -> Rules b -> Rules b #

(<*) :: Rules a -> Rules b -> Rules a #

Functor Rules 
Instance details

Defined in Hakyll.Core.Rules.Internal

Methods

fmap :: (a -> b) -> Rules a -> Rules b #

(<$) :: a -> Rules b -> Rules a #

Monad Rules 
Instance details

Defined in Hakyll.Core.Rules.Internal

Methods

(>>=) :: Rules a -> (a -> Rules b) -> Rules b #

(>>) :: Rules a -> Rules b -> Rules b #

return :: a -> Rules a #

MonadMetadata Rules 
Instance details

Defined in Hakyll.Core.Rules.Internal

class Writable a where #

Describes an item that can be saved to the disk

Methods

write :: FilePath -> Item a -> IO () #

Save an item to the given filepath

Instances

Instances details
Writable Html 
Instance details

Defined in Hakyll.Core.Writable

Methods

write :: FilePath -> Item Html -> IO () #

Writable ByteString 
Instance details

Defined in Hakyll.Core.Writable

Methods

write :: FilePath -> Item ByteString -> IO () #

Writable ByteString 
Instance details

Defined in Hakyll.Core.Writable

Methods

write :: FilePath -> Item ByteString -> IO () #

Writable CopyFile 
Instance details

Defined in Hakyll.Core.File

Methods

write :: FilePath -> Item CopyFile -> IO () #

Writable TmpFile 
Instance details

Defined in Hakyll.Core.File

Methods

write :: FilePath -> Item TmpFile -> IO () #

Writable Biblio 
Instance details

Defined in Hakyll.Web.Pandoc.Biblio

Methods

write :: FilePath -> Item Biblio -> IO () #

Writable CSL 
Instance details

Defined in Hakyll.Web.Pandoc.Biblio

Methods

write :: FilePath -> Item CSL -> IO () #

Writable Redirect 
Instance details

Defined in Hakyll.Web.Redirect

Methods

write :: FilePath -> Item Redirect -> IO () #

Writable Template 
Instance details

Defined in Hakyll.Web.Template.Internal

Methods

write :: FilePath -> Item Template -> IO () #

Writable Template Source # 
Instance details

Defined in Hakyllbars.Ast

Methods

write :: FilePath -> Item Template -> IO () #

Writable () 
Instance details

Defined in Hakyll.Core.Writable

Methods

write :: FilePath -> Item () -> IO () #

Writable [Word8] 
Instance details

Defined in Hakyll.Core.Writable

Methods

write :: FilePath -> Item [Word8] -> IO () #

Writable [Char] 
Instance details

Defined in Hakyll.Core.Writable

Methods

write :: FilePath -> Item [Char] -> IO () #

debugCompiler :: String -> Compiler () #

Compiler for debugging purposes. Passes a message to the debug logger that is printed in verbose mode.

withErrorMessage :: String -> Compiler a -> Compiler a #

Prepend an error line to the error, if there is one. This allows you to add helpful context to error messages.

Since: hakyll-4.13.0

noResult :: String -> Compiler a #

Fail so that it is treated as non-defined in an $if()$ branching Hakyll.Web.Template macro, and alternative Contexts are tried

Since: hakyll-4.13.0

unsafeCompiler :: IO a -> Compiler a #

Run an IO computation without dependencies in a Compiler. You probably want recompilingUnsafeCompiler instead.

cached :: (Binary a, Typeable a) => String -> Compiler a -> Compiler a #

Turn on caching for a compilation value to avoid recomputing it on subsequent Hakyll runs. The storage key consists of the underlying identifier of the compiled ressource and the given name.

saveSnapshot :: (Binary a, Typeable a) => Snapshot -> Item a -> Compiler (Item a) #

Save a snapshot of the item. This function returns the same item, which convenient for building >>= chains.

getResourceString :: Compiler (Item String) #

Get the full contents of the matched source file as a string.

getResourceBody :: Compiler (Item String) #

Get the full contents of the matched source file as a string, but without metadata preamble, if there was one.

getRoute :: Identifier -> Compiler (Maybe FilePath) #

Get the route for a specified item

makeItem :: a -> Compiler (Item a) #

Create an item from the underlying identifier and a given value.

loadSnapshotBody :: (Binary a, Typeable a) => Identifier -> Snapshot -> Compiler a #

A shortcut for only requiring the body for a specific snapshot of an item

loadBody :: (Binary a, Typeable a) => Identifier -> Compiler a #

A shortcut for only requiring the body of an item.

loadBody = fmap itemBody . load

loadSnapshot :: (Binary a, Typeable a) => Identifier -> Snapshot -> Compiler (Item a) #

Require a specific snapshot of an item.

load :: (Binary a, Typeable a) => Identifier -> Compiler (Item a) #

Load an item compiled elsewhere. If the required item is not yet compiled, the build system will take care of that automatically.

withItemBody :: (a -> Compiler b) -> Item a -> Compiler (Item b) #

Perform a compiler action on the item body. This is the same as traverse, but looks less intimidating.

withItemBody = traverse

itemSetBody :: a -> Item b -> Item a #

data Item a #

Constructors

Item 

Instances

Instances details
Foldable Item 
Instance details

Defined in Hakyll.Core.Item

Methods

fold :: Monoid m => Item m -> m #

foldMap :: Monoid m => (a -> m) -> Item a -> m #

foldMap' :: Monoid m => (a -> m) -> Item a -> m #

foldr :: (a -> b -> b) -> b -> Item a -> b #

foldr' :: (a -> b -> b) -> b -> Item a -> b #

foldl :: (b -> a -> b) -> b -> Item a -> b #

foldl' :: (b -> a -> b) -> b -> Item a -> b #

foldr1 :: (a -> a -> a) -> Item a -> a #

foldl1 :: (a -> a -> a) -> Item a -> a #

toList :: Item a -> [a] #

null :: Item a -> Bool #

length :: Item a -> Int #

elem :: Eq a => a -> Item a -> Bool #

maximum :: Ord a => Item a -> a #

minimum :: Ord a => Item a -> a #

sum :: Num a => Item a -> a #

product :: Num a => Item a -> a #

Traversable Item 
Instance details

Defined in Hakyll.Core.Item

Methods

traverse :: Applicative f => (a -> f b) -> Item a -> f (Item b) #

sequenceA :: Applicative f => Item (f a) -> f (Item a) #

mapM :: Monad m => (a -> m b) -> Item a -> m (Item b) #

sequence :: Monad m => Item (m a) -> m (Item a) #

Functor Item 
Instance details

Defined in Hakyll.Core.Item

Methods

fmap :: (a -> b) -> Item a -> Item b #

(<$) :: a -> Item b -> Item a #

Show a => Show (Item a) 
Instance details

Defined in Hakyll.Core.Item

Methods

showsPrec :: Int -> Item a -> ShowS #

show :: Item a -> String #

showList :: [Item a] -> ShowS #

Binary a => Binary (Item a) 
Instance details

Defined in Hakyll.Core.Item

Methods

put :: Item a -> Put #

get :: Get (Item a) #

putList :: [Item a] -> Put #

FromValue (Item a) a Source # 
Instance details

Defined in Hakyllbars.Context

IntoValue (Item a) a Source # 
Instance details

Defined in Hakyllbars.Context

type Snapshot = String #

Whilst compiling an item, it possible to save multiple snapshots of it, and not just the final result.

data Compiler a #

A monad which lets you compile items and takes care of dependency tracking for you.

Instances

Instances details
MonadFail Compiler 
Instance details

Defined in Hakyll.Core.Compiler.Internal

Methods

fail :: String -> Compiler a #

Alternative Compiler

Trying alternative compilers if the first fails, regardless whether through fail, throwError or noResult. Aggregates error messages if all fail.

Instance details

Defined in Hakyll.Core.Compiler.Internal

Methods

empty :: Compiler a #

(<|>) :: Compiler a -> Compiler a -> Compiler a #

some :: Compiler a -> Compiler [a] #

many :: Compiler a -> Compiler [a] #

Applicative Compiler 
Instance details

Defined in Hakyll.Core.Compiler.Internal

Methods

pure :: a -> Compiler a #

(<*>) :: Compiler (a -> b) -> Compiler a -> Compiler b #

liftA2 :: (a -> b -> c) -> Compiler a -> Compiler b -> Compiler c #

(*>) :: Compiler a -> Compiler b -> Compiler b #

(<*) :: Compiler a -> Compiler b -> Compiler a #

Functor Compiler 
Instance details

Defined in Hakyll.Core.Compiler.Internal

Methods

fmap :: (a -> b) -> Compiler a -> Compiler b #

(<$) :: a -> Compiler b -> Compiler a #

Monad Compiler 
Instance details

Defined in Hakyll.Core.Compiler.Internal

Methods

(>>=) :: Compiler a -> (a -> Compiler b) -> Compiler b #

(>>) :: Compiler a -> Compiler b -> Compiler b #

return :: a -> Compiler a #

MonadMetadata Compiler

Access provided metadata from anywhere

Instance details

Defined in Hakyll.Core.Compiler.Internal

MonadError [String] Compiler

Compilation may fail with multiple error messages. catchError handles errors from throwError, fail and noResult

Instance details

Defined in Hakyll.Core.Compiler.Internal

Methods

throwError :: [String] -> Compiler a #

catchError :: Compiler a -> ([String] -> Compiler a) -> Compiler a #

IntoValue (TemplateRunner a (ContextValue a)) a Source # 
Instance details

Defined in Hakyllbars.Context

(IntoValue v a, FromValue w a) => FromValue (FunctionValue v w a) a Source # 
Instance details

Defined in Hakyllbars.Context

(FromValue v a, IntoValue w a) => IntoValue (FunctionValue v w a) a Source # 
Instance details

Defined in Hakyllbars.Context

(IntoValue v a, IntoValue x a, FromValue w a) => FromValue (FunctionValue2 v x w a) a Source # 
Instance details

Defined in Hakyllbars.Context

(FromValue v a, FromValue x a, IntoValue w a) => IntoValue (FunctionValue2 v x w a) a Source # 
Instance details

Defined in Hakyllbars.Context

(IntoValue v a, IntoValue x a, IntoValue y a, FromValue w a) => FromValue (FunctionValue3 v x y w a) a Source # 
Instance details

Defined in Hakyllbars.Context

(FromValue v a, FromValue x a, FromValue y a, IntoValue w a) => IntoValue (FunctionValue3 v x y w a) a Source # 
Instance details

Defined in Hakyllbars.Context

Methods

intoValue :: FunctionValue3 v x y w a -> ContextValue a Source #

(IntoValue v a, IntoValue x a, IntoValue y a, IntoValue z a, FromValue w a) => FromValue (FunctionValue4 v x y z w a) a Source # 
Instance details

Defined in Hakyllbars.Context

(FromValue v a, FromValue x a, FromValue y a, FromValue z a, IntoValue w a) => IntoValue (FunctionValue4 v x y z w a) a Source # 
Instance details

Defined in Hakyllbars.Context

Methods

intoValue :: FunctionValue4 v x y z w a -> ContextValue a Source #

composeRoutes #

Arguments

:: Routes

First route to apply

-> Routes

Second route to apply

-> Routes

Resulting route

Compose two routes where the first route is applied before the second. So f `composeRoutes` g is more or less equivalent with g . f.

Warning: If the first route fails (e.g. when using matchRoute), Hakyll will not apply the second route (if you need Hakyll to try the second route, use <> on Routes instead).

Examples

Expand

Route that applies two transformations

-- e.g. file on disk: '<project-directory>/posts/hakyll.md'

-- 'hakyll.md' source file implicitly gets filepath as identifier:
-- 'posts/hakyll.md'
match "posts/*" $ do

    -- compilation result is written to '<destination-directory>/hakyll.html'
    route $ gsubRoute "posts/" (const "") `composeRoutes` setExtension "html"

    compile pandocCompiler

The identifier here is that of the underlying item being processed and is interpreted as an destination filepath. See Identifier for details. Note how we first remove the "posts/" substring from that destination filepath with gsubRoute and then replace the extension with setExtension.

metadataRoute #

Arguments

:: (Metadata -> Routes)

Wrapped route construction function

-> Routes

Resulting route

Wrapper function around other route construction functions to get access to the metadata (of the underlying item being processed) and use that for the destination filepath construction. Warning: you have to __ensure that the accessed metadata fields actually exists__.

Examples

Expand

Route that uses a custom slug markdown metadata field

To create a search engine optimized yet human-readable url, we can introduce a slug metadata field to our files, e.g. like in the following Markdown file: 'posts/hakyll.md'

---
title: Hakyll Post
slug: awesome-post
...
---
In this blog post we learn about Hakyll ...

Then we can construct a route whose destination filepath is based on that field:

match "posts/*" $ do

    -- compilation result is written to '<destination-directory>/awesome-post.html'
    route $ metadataRoute $ \meta ->
        constRoute $ fromJust (lookupString "slug" meta) <> ".html"

    compile pandocCompiler

Note how we wrap metadataRoute around the constRoute function and how the slug is looked up from the markdown field to construct the destination filepath. You can use helper functions like lookupString to access a specific metadata field.

gsubRoute #

Arguments

:: String

Pattern to repeatedly match against in the underlying identifier

-> (String -> String)

Replacement function to apply to the matched substrings

-> Routes

Resulting route

Create a "substituting" route that searches for substrings (in the underlying identifier) that match the given pattern and transforms them according to the given replacement function. The identifier here is that of the underlying item being processed and is interpreted as an destination filepath. It's normally the filepath of the source file being processed. See Identifier for details.

Hint: The name "gsub" comes from a similar function in [R](https://www.r-project.org) and can be read as "globally substituting" (globally in the Unix sense of repeated, not just once).

Examples

Expand

Route that replaces part of the filepath

-- e.g. file on disk: '<project-directory>/posts/hakyll.md'

-- 'hakyll.md' source file implicitly gets filepath as identifier:
-- 'posts/hakyll.md'
match "posts/*" $ do

    -- compilation result is written to '<destination-directory>/haskell/hakyll.md'
    route $ gsubRoute "posts/" (const "haskell/")

    compile getResourceBody

Note that "posts/" is replaced with "haskell/" in the destination filepath.

Route that removes part of the filepath

-- implicitly gets identifier: 'tags/rss/bar.xml'
create ["tags/rss/bar.xml"] $ do

    -- compilation result is written to '<destination-directory>/tags/bar.xml'
    route $ gsubRoute "rss/" (const "")

    compile ...

Note that "rss/" is removed from the destination filepath.

constRoute :: FilePath -> Routes #

Create a route that writes the compiled item to the given destination filepath (ignoring any identifier or other data about the item being processed). Warning: you should __use a specific destination path only for a single file in a single compilation rule__. Otherwise it's unclear which of the contents should be written to that route.

Examples

Expand

Route to a specific filepath

-- implicitly gets identifier: 'main' (ignored on next line)
create ["main"] $ do

    -- compilation result is written to '<destination-directory>/index.html'
    route $ constRoute "index.html"

    compile $ makeItem ("<h1>Hello World</h1>" :: String)

customRoute #

Arguments

:: (Identifier -> FilePath)

Destination filepath construction function

-> Routes

Resulting route

Create a route where the destination filepath is built with the given construction function. The provided identifier for that function is normally the filepath of the source file being processed. See Identifier for details.

Examples

Expand

Route that appends a custom extension

-- e.g. file on disk: '<project-directory>/posts/hakyll.md'

-- 'hakyll.md' source file implicitly gets filepath as identifier:
-- 'posts/hakyll.md'
match "posts/*" $ do

    -- compilation result is written to '<destination-directory>/posts/hakyll.md.html'
    route $ customRoute ((<> ".html") . toFilePath)

    compile pandocCompiler

Note that the last part of the destination filepath becomes .md.html

matchRoute :: Pattern -> Routes -> Routes #

Apply the route if the identifier matches the given pattern, fail otherwise

setExtension :: String -> Routes #

Create a route like idRoute that interprets the identifier (of the item being processed) as the destination filepath but also sets (or replaces) the extension suffix of that path. This identifier is normally the filepath of the source file being processed. See Identifier for details.

Examples

Expand

Route with an existing extension

-- e.g. file on disk: '<project-directory>/posts/hakyll.md'

-- 'hakyll.md' source file implicitly gets filepath as identifier:
-- 'posts/hakyll.md'
match "posts/*" $ do

    -- compilation result is written to '<destination-directory>/posts/hakyll.html'
    route (setExtension "html")

    compile pandocCompiler

Route without an existing extension

-- implicitly gets identifier: 'about'
create ["about"] $ do

    -- compilation result is written to '<destination-directory>/about.html'
    route (setExtension "html")

    compile $ makeItem ("Hello world" :: String)

idRoute :: Routes #

An "identity" route that interprets the identifier (of the item being processed) as the destination filepath. This identifier is normally the filepath of the source file being processed. See Identifier for details.

Examples

Expand

Route when using match

-- e.g. file on disk: '<project-directory>/posts/hakyll.md'

-- 'hakyll.md' source file implicitly gets filepath as identifier:
-- 'posts/hakyll.md'
match "posts/*" $ do

    -- compilation result is written to '<destination-directory>/posts/hakyll.md'
    route idRoute

    compile getResourceBody

data Routes #

Type used for a route

Instances

Instances details
Monoid Routes 
Instance details

Defined in Hakyll.Core.Routes

Semigroup Routes 
Instance details

Defined in Hakyll.Core.Routes

data Dependency #

Instances

Instances details
Show Dependency 
Instance details

Defined in Hakyll.Core.Dependencies

Binary Dependency 
Instance details

Defined in Hakyll.Core.Dependencies

(.||.) :: Pattern -> Pattern -> Pattern infixr 2 #

|| for patterns: the given identifier must match any subterm

(.&&.) :: Pattern -> Pattern -> Pattern infixr 3 #

&& for patterns: the given identifier must match both subterms

hasNoVersion :: Pattern #

Match only if the identifier has no version set, e.g.

"foo/*.markdown" .&&. hasNoVersion

hasVersion :: String -> Pattern #

Specify a version, e.g.

"foo/*.markdown" .&&. hasVersion "pdf"

fromRegex :: String -> Pattern #

Create a Pattern from a regex

Example:

regex "^foo/[^x]*$

fromList :: [Identifier] -> Pattern #

Create a Pattern from a list of Identifiers it should match.

Warning: use this carefully with hasNoVersion and hasVersion. The Identifiers in the list already have versions assigned, and the pattern will then only match the intersection of both versions.

A more concrete example,

fromList ["foo.markdown"] .&&. hasVersion "pdf"

will not match anything! The "foo.markdown" Identifier has no version assigned, so the LHS of .&&. will only match this Identifier with no version. The RHS only matches Identifiers with version set to "pdf" -- hence, this pattern matches nothing.

The correct way to use this is:

fromList $ map (setVersion $ Just "pdf") ["foo.markdown"]

data Pattern #

Type that allows matching on identifiers

Instances

Instances details
Monoid Pattern 
Instance details

Defined in Hakyll.Core.Identifier.Pattern.Internal

Semigroup Pattern 
Instance details

Defined in Hakyll.Core.Identifier.Pattern.Internal

Show Pattern 
Instance details

Defined in Hakyll.Core.Identifier.Pattern.Internal

Binary Pattern 
Instance details

Defined in Hakyll.Core.Identifier.Pattern.Internal

Methods

put :: Pattern -> Put #

get :: Get Pattern #

putList :: [Pattern] -> Put #

toFilePath :: Identifier -> FilePath #

Convert an identifier back to a relative FilePath.

fromFilePath :: FilePath -> Identifier #

Parse an identifier from a file path string. For example,

-- e.g. file on disk: 'posts/hakyll.md'
match "posts/*" $ do                                          -- saved with implicit identifier 'posts/hakyll.md'
    compile pandocCompiler

match "about/*" $ do
    compile $ do
        compiledPost <- load (fromFilePath "posts/hakyll.md") -- load with explicit identifier
        ...

data Identifier #

A key data type to identify a compiled Item in the Store. Conceptually, it's a combination of a file path and a version name. The version is used only when a file is compiled within a rule using the version wrapper function (the same source file can be compiled into several items in the store, so the version exists to distinguish them). Use functions like fromFilePath, setVersion, getMatches to build an Identifier.

Usage Examples

Expand

Normally, compiled items are saved to the store by Rules with an automatic, implicit identifier and loaded from the store by the user in another rule with a manual, explicit identifier.

Identifiers when using match. Using match builds an implicit identifier that corresponds to the expanded, relative path of the source file on disk (relative to the project directory configured with providerDirectory):

-- e.g. file on disk: 'posts/hakyll.md'
match "posts/*" $ do                                          -- saved with implicit identifier 'posts/hakyll.md'
    compile pandocCompiler

match "about/*" $ do
    compile $ do
        compiledPost <- load (fromFilePath "posts/hakyll.md") -- load with explicit identifier
        ...

Normally, the identifier is only explicitly created to pass to one of the load functions.

Identifiers when using create. Using create (thereby inventing a file path with no underlying file on disk) builds an implicit identifier that corresponds to the invented file path:

create ["index.html"] $ do                                -- saved with implicit identifier 'index.html'
    compile $ makeItem ("Hello world" :: String)

match "about/*" $ do
    compile $ do
        compiledIndex <- load (fromFilePath "index.html") -- load with an explicit identifier
        ...

Identifiers when using versions. With version the same file can be compiled into several items in the store. A version name is needed to distinguish them:

-- e.g. file on disk: 'posts/hakyll.md'
match "posts/*" $ do                              -- saved with implicit identifier ('posts/hakyll.md', no-version)
    compile pandocCompiler

match "posts/*" $ version "raw" $ do              -- saved with implicit identifier ('posts/hakyll.md', version raw)
    compile getResourceBody

match "about/*" $ do
    compile $ do
        compiledPost <- load (fromFilePath "posts/hakyll.md")                      -- load no-version version
        rawPost <- load . setVersion (Just "raw") $ fromFilePath "posts/hakyll.md" -- load version raw
    ...

Use setVersion to set (or replace) the version of an identifier like fromFilePath "posts/hakyll.md".

Instances

Instances details
IsString Identifier 
Instance details

Defined in Hakyll.Core.Identifier

Show Identifier 
Instance details

Defined in Hakyll.Core.Identifier

Binary Identifier 
Instance details

Defined in Hakyll.Core.Identifier

NFData Identifier 
Instance details

Defined in Hakyll.Core.Identifier

Methods

rnf :: Identifier -> () #

Eq Identifier 
Instance details

Defined in Hakyll.Core.Identifier

Ord Identifier 
Instance details

Defined in Hakyll.Core.Identifier

doesFileExist :: FilePath -> IO Bool #

The operation doesFileExist returns True if the argument file exists and is not a directory, and False otherwise.

copyFile #

Arguments

:: FilePath

Source filename

-> FilePath

Destination filename

-> IO () 

Copy a file with its permissions. If the destination file already exists, it is replaced atomically. Neither path may refer to an existing directory. No exceptions are thrown if the permissions could not be copied.

createDirectoryIfMissing #

Arguments

:: Bool

Create its parents too?

-> FilePath

The path to the directory you want to make

-> IO () 

createDirectoryIfMissing parents dir creates a new directory dir if it doesn't exist. If the first argument is True the function will also create all parent directories if they are missing.

splitDirectories :: FilePath -> [FilePath] #

Just as splitPath, but don't add the trailing slashes to each element.

         splitDirectories "/directory/file.ext" == ["/","directory","file.ext"]
         splitDirectories "test/file" == ["test","file"]
         splitDirectories "/test/file" == ["/","test","file"]
Windows: splitDirectories "C:\\test\\file" == ["C:\\", "test", "file"]
         Valid x => joinPath (splitDirectories x) `equalFilePath` x
         splitDirectories "" == []
Windows: splitDirectories "C:\\test\\\\\\file" == ["C:\\", "test", "file"]
         splitDirectories "/test///file" == ["/","test","file"]

(</>) :: FilePath -> FilePath -> FilePath infixr 5 #

Combine two paths with a path separator. If the second path starts with a path separator or a drive letter, then it returns the second. The intention is that readFile (dir </> file) will access the same file as setCurrentDirectory dir; readFile file.

Posix:   "/directory" </> "file.ext" == "/directory/file.ext"
Windows: "/directory" </> "file.ext" == "/directory\\file.ext"
         "directory" </> "/file.ext" == "/file.ext"
Valid x => (takeDirectory x </> takeFileName x) `equalFilePath` x

Combined:

Posix:   "/" </> "test" == "/test"
Posix:   "home" </> "bob" == "home/bob"
Posix:   "x:" </> "foo" == "x:/foo"
Windows: "C:\\foo" </> "bar" == "C:\\foo\\bar"
Windows: "home" </> "bob" == "home\\bob"

Not combined:

Posix:   "home" </> "/bob" == "/bob"
Windows: "home" </> "C:\\bob" == "C:\\bob"

Not combined (tricky):

On Windows, if a filepath starts with a single slash, it is relative to the root of the current drive. In [1], this is (confusingly) referred to as an absolute path. The current behavior of </> is to never combine these forms.

Windows: "home" </> "/bob" == "/bob"
Windows: "home" </> "\\bob" == "\\bob"
Windows: "C:\\home" </> "\\bob" == "\\bob"

On Windows, from [1]: "If a file name begins with only a disk designator but not the backslash after the colon, it is interpreted as a relative path to the current directory on the drive with the specified letter." The current behavior of </> is to never combine these forms.

Windows: "D:\\foo" </> "C:bar" == "C:bar"
Windows: "C:\\foo" </> "C:bar" == "C:bar"

takeDirectory :: FilePath -> FilePath #

Get the directory name, move up one level.

          takeDirectory "/directory/other.ext" == "/directory"
          isPrefixOf (takeDirectory x) x || takeDirectory x == "."
          takeDirectory "foo" == "."
          takeDirectory "/" == "/"
          takeDirectory "/foo" == "/"
          takeDirectory "/foo/bar/baz" == "/foo/bar"
          takeDirectory "/foo/bar/baz/" == "/foo/bar/baz"
          takeDirectory "foo/bar/baz" == "foo/bar"
Windows:  takeDirectory "foo\\bar" == "foo"
Windows:  takeDirectory "foo\\bar\\\\" == "foo\\bar"
Windows:  takeDirectory "C:\\" == "C:\\"

takeFileName :: FilePath -> FilePath #

Get the file name.

takeFileName "/directory/file.ext" == "file.ext"
takeFileName "test/" == ""
isSuffixOf (takeFileName x) x
takeFileName x == snd (splitFileName x)
Valid x => takeFileName (replaceFileName x "fred") == "fred"
Valid x => takeFileName (x </> "fred") == "fred"
Valid x => isRelative (takeFileName x)

splitFileName :: FilePath -> (String, String) #

Split a filename into directory and file. </> is the inverse. The first component will often end with a trailing slash.

splitFileName "/directory/file.ext" == ("/directory/","file.ext")
Valid x => uncurry (</>) (splitFileName x) == x || fst (splitFileName x) == "./"
Valid x => isValid (fst (splitFileName x))
splitFileName "file/bob.txt" == ("file/", "bob.txt")
splitFileName "file/" == ("file/", "")
splitFileName "bob" == ("./", "bob")
Posix:   splitFileName "/" == ("/","")
Windows: splitFileName "c:" == ("c:","")
Windows: splitFileName "\\\\?\\A:\\fred" == ("\\\\?\\A:\\","fred")

dropExtension :: FilePath -> FilePath #

Remove last extension, and the "." preceding it.

dropExtension "/directory/path.ext" == "/directory/path"
dropExtension x == fst (splitExtension x)