lang en ja

HakyllでRouteを変更した上で内部リンクを使う

Published Last Update author
2024/05/28 2024/05/28 Shumpei Tanaka

Hakyll で Route を変更して markdown を pandoc compiler を通してもリンク先は自動で更新されない。

このため、markdown 内の link を手動で書き替えてやる必要がある

Hakyll で定義されている withUrlsを使用するとString->Stringの変換を 各種 URL に適用することができる。これを使用して変更したい URL のみ上書きする。

実装を用いて説明する。

  • parseInnerLinks: parseInnerLinkwithUrls ですべての 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 =
        url
  • parsePostLink: #を含んでいる(特定のセクションへのリンク)を考慮した処理。 #以前の 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

Say thank you

役立ったら下のリンクから支援をもらえると嬉しい
paypal.me Badge paypal.me Badge