{-# LANGUAGE GHC2021 #-}
{-# LANGUAGE OverloadedStrings #-}
-- | Image attribute filter.
--
--   Walks all @Image@ inlines and:
--   * Adds @loading="lazy"@ to every image.
--   * Adds @data-lightbox="true"@ to images that are NOT already wrapped in
--     a @Link@ inline (i.e. the image is not itself a hyperlink).
--
--   The wrapping-link check is done by walking the document with two passes:
--   a block-level walk that handles the common @Link [Image …] …@ pattern,
--   and a plain image walk that stamps @loading="lazy"@ on everything else.
module Filters.Images (apply) where

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

-- | Apply image attribute injection to the entire document.
apply :: Pandoc -> Pandoc
apply = walk transformInline

-- ---------------------------------------------------------------------------
-- Core transformation
-- ---------------------------------------------------------------------------

-- | Process a single inline node.
--
--   * @Link … [Image …] …@  — image inside a link: add only @loading="lazy"@.
--   * @Image …@             — standalone image: add both @loading="lazy"@ and
--                             @data-lightbox="true"@.
--   * Anything else         — pass through unchanged.
transformInline :: Inline -> Inline
transformInline (Link lAttr ils lTarget) =
    -- Recurse into link contents, but mark any images inside as linked
    -- (so they receive lazy loading only, no lightbox marker).
    Link lAttr (map (addLazyOnly) ils) lTarget
  where
    addLazyOnly (Image iAttr alt iTarget) =
        Image (addAttr "loading" "lazy" iAttr) alt iTarget
    addLazyOnly x = x
transformInline (Image attr alt target) =
    Image (addAttr "data-lightbox" "true" (addAttr "loading" "lazy" attr)) alt target
transformInline x = x

-- ---------------------------------------------------------------------------
-- Attribute helpers
-- ---------------------------------------------------------------------------

-- | Prepend a key=value pair to an @Attr@'s key-value list (if not already
--   present, to avoid duplicating attributes that come from Markdown).
addAttr :: Text -> Text -> Attr -> Attr
addAttr k v (ident, classes, kvs)
    | any ((== k) . fst) kvs = (ident, classes, kvs)
    | otherwise               = (ident, classes, (k, v) : kvs)
