tl;dr – You could use Beerend Lauwers's hakyll-extra
package (doesn't seem to be on hackage
yet), which provides a relativizeUrl
macro. Or, implement your own as follows:
If you don't have too many links, and don't fancy introducing a CSS parser just in order to do this, you could just create a function field - effectively, a macro -- which allows you to call, e.g. relativize("/some/url")
from within the page. (I ran into a similar problem, because I wanted to relativize links to a stylesheet for use only by old versions of Internet Explorer; and to TagSoup
, the links looked as if they were within comments, so it didn't process them.)
First, we need to write a version of relativizeUrls
which just operates on a single URL:
import Data.List as L
-- | Relativize URL. Same logic as "relativizeUrlsWith" in
-- Hakyll.Web.Html.RelativizeUrls, but for just one url.
relativizeUrl :: String -- ^ Path to the site root
-> String -- ^ link to relativize
-> String -- ^ Resulting link
relativizeUrl root = rel
where
isRel :: String -> Bool
isRel x = "/" `L.isPrefixOf` x && not ("//" `L.isPrefixOf` x)
rel x = if isRel x then root ++ x else x
Then, we define a "function field" which can be added to contexts.
import Data.Maybe (maybe)
-- ugh. ugly name.
relativizeFuncField :: Context a
relativizeFuncField = functionField "relativize" relativize
where
relativize :: [String] -> Item a -> Compiler String
relativize args item = do
siteRoot <- getRoot <$> (getRoute $ itemIdentifier item)
arg <- case args of
[arg] -> return arg
_ -> error "relativize: expected only 1 arg"
return $ relativizeUrl siteRoot arg
getRoot :: Maybe String -> String
getRoot = maybe (error "relativize: couldn't get route") toSiteRoot
Then, anywhere you want to use this macro, instead of using, say, defaultContext
, use relativizeFuncField <> defaultContext
. e.g.:
import Data.Monoid( (<>) )
main =
-- ...
match (fromList ["about.rst", "contact.markdown"]) $ do
route $ setExtension "html"
compile $ pandocCompiler
>>= loadAndApplyTemplate "templates/default.html" (relativizeFuncField <> defaultContext)
>>= relativizeUrls
So, finally, that means that within a file, you can write $relativize("/path/to/file")$
in any spot where TagSoup
isn't already relativizing links.
Hope that's of use :)
(This was using Hakyll 4.9.0.0, but I assume other 4.X versions are much the same.)
edited: p.s., many thanks to Beerend Lauwers, who explained Hakyll function fields in his post here
edited again: d'oh. I didn't see that Beerend has actually already put a relativizeUrl
function in his hakyll-extra
package.