{-# LANGUAGE GHC2021 #-}
{-# LANGUAGE OverloadedStrings #-}
-- | External link classification.
--
--   Walks all @Link@ inlines and:
--   * Adds @class="link-external"@ to any link whose URL starts with
--     @http://@ or @https://@ and is not on the site's own domain.
--   * Adds @data-link-icon@ / @data-link-icon-type@ attributes for
--     per-domain brand icons (wikipedia, arxiv, doi, github, external).
--   * Adds @target="_blank" rel="noopener noreferrer"@ to external links.
module Filters.Links (apply) where

import           Data.Text            (Text)
import qualified Data.Text            as T
import           Text.Pandoc.Definition
import           Text.Pandoc.Walk     (walk)

-- | Apply link classification to the entire document.
apply :: Pandoc -> Pandoc
apply = walk classifyLink

classifyLink :: Inline -> Inline
classifyLink (Link (ident, classes, kvs) ils (url, title))
    | isExternal url =
        let icon     = domainIcon url
            classes' = classes ++ ["link-external"]
            kvs'     = kvs
                       ++ [("target",             "_blank")]
                       ++ [("rel",                "noopener noreferrer")]
                       ++ [("data-link-icon",      icon)]
                       ++ [("data-link-icon-type", "svg")]
        in  Link (ident, classes', kvs') ils (url, title)
classifyLink x = x

-- ---------------------------------------------------------------------------
-- Helpers
-- ---------------------------------------------------------------------------

isExternal :: Text -> Bool
isExternal url =
    ("http://"  `T.isPrefixOf` url || "https://" `T.isPrefixOf` url)
    && not ("levineuwirth.org" `T.isInfixOf` url)

-- | Icon name for the link, matching a file in /images/link-icons/<name>.svg.
domainIcon :: Text -> Text
domainIcon url
    | "wikipedia.org" `T.isInfixOf` url = "wikipedia"
    | "arxiv.org"     `T.isInfixOf` url = "arxiv"
    | "doi.org"       `T.isInfixOf` url = "doi"
    | "github.com"    `T.isInfixOf` url = "github"
    | otherwise                          = "external"
