tl;dr – 您可以使用 Beerend Lauwers 的hakyll-extra
包(似乎还没有启用hackage
),它提供了一个relativizeUrl
宏。或者,按如下方式实现您自己的:
如果您没有太多链接,并且不想仅仅为了做到这一点而引入 CSS 解析器,您可以创建一个函数字段 - 实际上是一个宏 - 它允许您调用,例如relativize("/some/url")
从页。(我遇到了类似的问题,因为我想将指向样式表的链接相对化以供旧版本的 Internet Explorer 使用;而对于TagSoup
,这些链接看起来好像它们在评论中,所以它没有处理它们。)
首先,我们需要编写一个relativizeUrls
只对单个 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
然后,我们定义一个可以添加到上下文中的“函数字段”。
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
然后,在任何你想使用这个宏的地方,而不是使用,比如说defaultContext
,使用relativizeFuncField <> defaultContext
。例如:
import Data.Monoid( (<>) )
main =
-- ...
match (fromList ["about.rst", "contact.markdown"]) $ do
route $ setExtension "html"
compile $ pandocCompiler
>>= loadAndApplyTemplate "templates/default.html" (relativizeFuncField <> defaultContext)
>>= relativizeUrls
所以,最后,这意味着在一个文件中,你可以在任何没有相对化链接$relativize("/path/to/file")$
的地方写。TagSoup
希望这是有用的:
)(这是使用 Hakyll 4.9.0.0,但我认为其他 4.X 版本大致相同。)
编辑:ps,非常感谢 Beerend Lauwers,他在这里的帖子中解释了 Hakyll 函数字段
再次编辑:d'oh。我没有看到Beerend实际上已经在他的包中放入了一个relativizeUrl
函数。hakyll-extra