{-# LANGUAGE OverloadedRecordDot #-} -- | -- Module : Zettel.Links -- Description : Calculate the backlinks and forward links for each Zettel -- Copyright : (c) 2023, Yann Herklotz -- License : GPL-3.0-only -- Maintainer : git [at] yannherklotz [dot] com -- Stability : experimental -- Portability : POSIX module Zettel.Links where import Data.List (nub) import qualified Data.Map.Strict as Map import qualified Data.Text as T import Text.Pandoc.Definition (Inline (..)) import Text.Pandoc.Shared (stringify) import Text.Pandoc.Walk (query, walk) import Zettel.Common import Zettel.Types gatherForwardIds :: Inline -> [ZettelId] gatherForwardIds (Link _ i _) | T.null ident = [] | otherwise = [ZettelId ident] where ident = parseIds $ stringify i gatherForwardIds (RawInline t v) | t == "markdown" && not (T.null parsed) = [ZettelId parsed] | otherwise = [] where parsed = T.takeWhile (/= '"') . T.drop 1 $ T.dropWhile (/= '"') v gatherForwardIds _ = [] addIdPresent :: ZettelGraph -> Maybe ZettelId -> [ZettelId] addIdPresent zg (Just ident) = [ident | ident `elem` Map.keys (unZettelGraph zg)] addIdPresent _ Nothing = [] forwardLinkNode :: ZettelGraph -> ZettelId -> Zettel -> Zettel forwardLinkNode zg ident zn = zn { zettelNext = nub ( query gatherForwardIds zn.zettelBody <> addIdPresent zg (defNextId ident) <> addIdPresent zg (defBranchId ident) ) } forwardLink :: ZettelGraph -> ZettelGraph forwardLink zg = ZettelGraph (Map.mapWithKey (forwardLinkNode zg) $ unZettelGraph zg) zg.zettelGraphBib backwardLinkNode :: ZettelGraph -> ZettelId -> Zettel -> Zettel backwardLinkNode graph ident node = Map.foldlWithKey' f node (unZettelGraph graph) where f :: Zettel -> ZettelId -> Zettel -> Zettel f l ident' zg | ident `elem` zg.zettelNext = l {zettelPrev = ident' : l.zettelPrev} | otherwise = l backwardLink :: ZettelGraph -> ZettelGraph backwardLink zg = ZettelGraph (Map.mapWithKey (backwardLinkNode zg) $ unZettelGraph zg) zg.zettelGraphBib updatePandocLinksInline :: Inline -> Inline updatePandocLinksInline l@(Link a i (_, t)) | not $ T.null ids = Link a i ("/zettel/" <> ids, t) | otherwise = l where ids = parseIds $ stringify i updatePandocLinksInline i = i updatePandocLinks :: ZettelGraph -> ZettelGraph updatePandocLinks = walk updatePandocLinksInline linkAll :: ZettelGraph -> ZettelGraph linkAll = refreshPandocMeta . backwardLink . forwardLink . updatePandocLinks