Hakyll で Route を変更して markdown を pandoc compiler を通してもリンク先は自動で更新されない。
このため、markdown 内の link を手動で書き替えてやる必要がある
Hakyll で定義されている withUrlsを使用するとString->Stringの変換を
各種 URL に適用することができる。これを使用して変更したい URL のみ上書きする。
実装を用いて説明する。
parseInnerLinks:parseInnerLinkをwithUrlsですべての URL に対して適用するparseInnerLink:/postsの接頭辞の url のみparsePostLinkを適用する
parseInnerLinks :: Item String -> Compiler (Item String)
parseInnerLinks = pure . fmap (withUrls parseInnerLink)
parseInnerLink :: String -> String
parseInnerLink url
| isExternal url = url
| "/posts" `L.isPrefixOf` url =
parsePostLink url
| otherwise =
urlparsePostLink:#を含んでいる(特定のセクションへのリンク)を考慮した処理。#以前の URL を変換し#以後を再結合するconvPostUrl:Routeの変更に使用したString->Stringの変換を再利用する。Identifierを取得する際、先頭の/が邪魔になるためtailで除去している。
parsePostLink :: String -> String
parsePostLink url = case map T.unpack . T.splitOn "#" $ T.pack url of
[base] -> addHtml . convPostUrl $ base
[base, section] -> (++ section) . (++ "#") . addHtml . convPostUrl $ base
convPostUrl :: String -> String
convPostUrl url = (++) "/" . getLangPath . fromFilePath $ tail url
addHtml :: String -> String
addHtml = (++ ".html")定義したparseInnerLinksは次にように使用することができる。
pandocCompiler
>>= loadAndApplyTemplate "templates/post.html" postCtx
>>= loadAndApplyTemplate "templates/default.html" postCtx
>>= parseInnerLinks
>>= relativizeUrls