packages feed

mdoc-0.1.0.0: src/Mdoc/Gen/Template.hs

{-# LANGUAGE TemplateHaskell #-}

-- |
--
-- Module      : Mdoc.Gen.Template
-- Copyright   : (c) 2026 Patrick Brisbin
-- License     : AGPL-3
-- Maintainer  : pbrisbin@gmail.com
-- Stability   : experimental
-- Portability : POSIX
module Mdoc.Gen.Template
  ( Template (..)
  , TemplateContents (..)
  , InterpolationValues (..)
  , interpolateTemplate
  ) where

import Mdoc.Prelude

import Data.ByteString.Lazy qualified as BSL
import Data.FileEmbed (embedFileRelative)
import Mdoc
import Mdoc.Input
import Mdoc.Interpolated
import Mdoc.Parse
import Mdoc.UpdateMdocdate

data Template
  = TemplateBuiltin1
  | TemplateBuiltin5
  | TemplateFile FilePath
  | TemplateBytes TemplateContents

data TemplateContents = TemplateContents
  { name :: String
  -- ^ Used in parse errors
  , bytes :: BSL.ByteString
  }

interpolateTemplate
  :: MonadIO m
  => InterpolationValues
  -> Template
  -> m Mdoc
interpolateTemplate vs = \case
  TemplateBuiltin1 -> interpolateTemplateContents vs builtin1
  TemplateBuiltin5 -> interpolateTemplateContents vs builtin5
  TemplateFile fp -> interpolateTemplateContents vs =<< getTemplateContents fp
  TemplateBytes c -> interpolateTemplateContents vs c

interpolateTemplateContents
  :: MonadIO m
  => InterpolationValues
  -> TemplateContents
  -> m Mdoc
interpolateTemplateContents vs c = do
  mdoc <-
    either exitParseError (pure . interpolate vs)
      $ parseMdocBytes c.name c.bytes

  updateMdocdate mdoc

getTemplateContents :: MonadIO m => FilePath -> m TemplateContents
getTemplateContents name = do
  bytes <- liftIO $ BSL.readFile name
  pure TemplateContents {name, bytes}

builtin1 :: TemplateContents
builtin1 =
  TemplateContents
    { name = "data/man1.template"
    , bytes = BSL.fromStrict $(embedFileRelative "data/man1.template")
    }

builtin5 :: TemplateContents
builtin5 =
  TemplateContents
    { name = "data/man5.template"
    , bytes = BSL.fromStrict $(embedFileRelative "data/man5.template")
    }