ronn-1.1.0.0: src/Ronn/Render.hs
-- |
--
-- Module : Ronn.Render
-- Copyright : (c) 2024 Patrick Brisbin
-- License : AGPL-3
-- Maintainer : pbrisbin@gmail.com
-- Stability : experimental
-- Portability : POSIX
module Ronn.Render
( ronnToText
-- * Rendering sub-parts, mostly useful in tests
, ronnGroupToText
, ronnLineToText
, ronnPartToText
) where
import Prelude
import Data.Text (Text, pack)
import Data.Text qualified as T
import Ronn.AST
ronnToText :: Ronn -> Text
ronnToText ronn =
T.unlines $
map ronnGroupToText $
Title ronn.name ronn.description
: concatMap ronnSectionToGroups ronn.sections
ronnSectionToGroups :: Section -> [Group]
ronnSectionToGroups section =
Header section.name : concatMap (ronnContentToGroups 0) section.content
ronnContentToGroups :: Int -> Content -> [Group]
ronnContentToGroups indentLevel = \case
Definitions defns ->
concatMap (ronnDefinitionToGroups $ indentLevel + 2) defns
Groups gs -> map (indentRonnGroup indentLevel) gs
ronnDefinitionToGroups :: Int -> Definition -> [Group]
ronnDefinitionToGroups indentLevel defn =
[ Lines
[ indentRonnLine indentLevel $ Line ["* " <> defn.name <> ":"]
, indentRonnLine nextIndentLevel defn.description
]
]
<> nested
where
nested = maybe [] (concatMap $ ronnContentToGroups nextIndentLevel) defn.content
nextIndentLevel = indentLevel + 2
ronnGroupToText :: Group -> Text
ronnGroupToText = T.unlines . map ronnLineToText . ronnGroupToLines
ronnGroupToLines :: Group -> [Line]
ronnGroupToLines = \case
Title ref description ->
let nameLine = ronnNameLine ref description
in [ nameLine
, Line [Raw $ T.replicate (ronnLineLength nameLine) "="]
]
Header name -> [Line ["##", Raw name]]
Lines ls -> ls
ronnNameLine :: ManRef -> [Part] -> Line
ronnNameLine ref =
Line . (Raw (manRefToText ref) :) . ("--" :)
ronnLineToText :: Line -> Text
ronnLineToText = T.unwords . map ronnPartToText . (.unwrap)
ronnPartToText :: Part -> Text
ronnPartToText = \case
Concat xs -> mconcat $ map ronnPartToText xs
Code x -> "`" <> ronnPartToText x <> "`"
UserInput x -> "`" <> ronnPartToText x <> "`"
Strong x -> "**" <> ronnPartToText x <> "**"
Variable x -> "<" <> ronnPartToText x <> ">"
Ephasis x -> "_" <> ronnPartToText x <> "_"
Brackets x -> "[" <> ronnPartToText x <> "]"
Parens x -> "(" <> ronnPartToText x <> ")"
Ref ref -> ronnPartToText $ Strong $ Raw $ manRefToText ref
Raw x -> x
manRefToText :: ManRef -> Text
manRefToText ref =
ref.name
<> "("
<> pack (show $ manSectionNumber ref.section)
<> ")"
ronnLineLength :: Line -> Int
ronnLineLength = T.length . ronnLineToText
indentRonnGroup :: Int -> Group -> Group
indentRonnGroup indentLevel = \case
g@Title {} -> g
g@Header {} -> g
Lines ls -> Lines $ map (indentRonnLine indentLevel) ls
-- | Prepends the given number of spaces to the first 'Part' of the line
indentRonnLine :: Int -> Line -> Line
indentRonnLine n = \case
Line [] -> Line []
Line (p : ps) -> Line $ (spaces <> p) : ps
where
spaces = Raw $ pack $ replicate n ' '