packages feed

gemoire-1.0.0: src/Gemoire/Converter/Markdown.hs

{-# LANGUAGE OverloadedStrings #-}

-- |
-- Module      :  Gemoire.Converter.Markdown
-- Copyright   :  (c) 2025 Sena
-- License     :  GPL-3.0-or-later
--
-- Maintainer  :  contact@sena.pink
-- Stability   :  stable
-- Portability :  portable
--
-- Default configuration and templates for Gemini to Markdown conversion
module Gemoire.Converter.Markdown
    ( -- * Defaults
      defMarkdownConversion
    , escapeContent
    , defDocument
    , defText
    , defLink
    , defH1
    , defH2
    , defH3
    , defList
    , defListItem
    , defQuote
    , defPre
    ) where

import Control.Arrow (second)
import Data.Char (isSpace)
import Data.HashMap.Strict (empty)
import Data.Text (Text)
import qualified Data.Text as T

import Gemoire.Converter.Types (Conversion (..))
import Gemoire.Template (Template, template)

defMarkdownConversion :: Conversion
defMarkdownConversion =
    Conversion
        { targetExtension = ".md"
        , escaper = escapeContent
        , preEscaper = id
        , attrEscaper = escapeContent
        , documentTemplate = defDocument
        , textTemplate = defText
        , linkTemplate = defLink
        , h1Template = defH1
        , h2Template = defH2
        , h3Template = defH3
        , listTemplates = (defList, defListItem)
        , quoteTemplate = defQuote
        , preTemplate = defPre
        , rewriteRules = []
        , conversionOverrides = empty
        }

escapeContent :: Text -> Text
escapeContent =
    replaceOnStart ">" "\\>"
        . replaceOnStart "-" "\\-"
        . replaceOnStart "+" "\\+"
        . replaceOnStart "*" "\\*"
        . replaceOnStart "#" "\\#"
        . T.replace "(" "\\("
        . T.replace ")" "\\)"
        . T.replace "[" "\\["
        . T.replace "]" "\\]"
        . T.replace "\\" "\\\\"

replaceOnStart :: Text -> Text -> Text -> Text
replaceOnStart a b text =
    uncurry (<>)
        . second (maybe text (b <>) . T.stripPrefix a)
        . T.span isSpace
        $ text

defDocument :: Template
defDocument = template "{$body$}\LF"

defText :: Template
defText = template "{$text$}  "

defLink :: Template
defLink = template "[{&description:link&}]({$link$})  "

defH1 :: Template
defH1 = template "# {$text$}"

defH2 :: Template
defH2 = template "## {$text$}"

defH3 :: Template
defH3 = template "### {$text$}"

defList :: Template
defList = template "{$items$}"

defListItem :: Template
defListItem = template "- {$text$}"

defQuote :: Template
defQuote = template "> {$text$}"

defPre :: Template
defPre =
    template . T.intercalate "\LF" $
        [ "```{$alt$}"
        , "{$text$}"
        , "```"
        ]