{-# LANGUAGE OverloadedRecordDot #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE NoFieldSelectors #-} module Commonmark.Initial ( Ann (..) , Block , Blocks , BlockF (..) , Inline , Inlines , InlineF (..) , pattern MkBlock , pattern MkInline ) where import Commonmark.Types ( Attributes , Format , HasAttributes (..) , IsBlock (..) , IsInline (..) , ListSpacing , ListType , Rangeable (..) , SourceRange ) import Control.Comonad.Cofree import Data.Eq.Deriving import Data.Text (Text) import Text.Show.Deriving data Ann = MkAnn { range :: SourceRange , attributes :: Attributes } deriving (Show, Eq) instance Semigroup Ann where a <> b = MkAnn (a.range <> b.range) (a.attributes <> b.attributes) instance Monoid Ann where mempty = MkAnn mempty mempty data InlineF r = LineBreak | SoftBreak | Str Text | Entity Text | EscapedChar Char | Emph [r] | Strong [r] | Link Text Text [r] | Image Text Text [r] | Code Text | RawInline Format Text deriving (Show, Eq, Functor, Foldable, Traversable) $(deriveShow1 ''InlineF) $(deriveEq1 ''InlineF) type Inline a = Cofree InlineF a pattern MkInline :: a -> InlineF (Inline a) -> Inline a pattern MkInline a body = a :< body {-# COMPLETE MkInline #-} type Inlines = [Inline Ann] rangedInline :: SourceRange -> Inline Ann -> Inline Ann rangedInline sr (MkInline ann body) = MkInline (ann <> MkAnn sr mempty) body addAttributesInline :: Attributes -> Inline Ann -> Inline Ann addAttributesInline attrs (MkInline ann body) = MkInline (ann <> MkAnn mempty attrs) body instance Rangeable Inlines where ranged sr = map $ rangedInline sr instance HasAttributes Inlines where addAttributes attrs = map $ addAttributesInline attrs mkInline :: (Monoid a) => InlineF (Inline a) -> Inline a mkInline = MkInline mempty instance IsInline Inlines where lineBreak = [mkInline LineBreak] softBreak = [mkInline SoftBreak] str t = [mkInline $ Str t] entity t = [mkInline $ Entity t] escapedChar c = [mkInline $ EscapedChar c] emph ils = [mkInline $ Emph ils] strong ils = [mkInline $ Strong ils] link d t desc = [mkInline $ Link d t desc] image s t desc = [mkInline $ Image s t desc] code t = [mkInline $ Code t] rawInline f t = [mkInline $ RawInline f t] data BlockF a r = Paragraph [Inline a] | Plain [Inline a] | ThematicBreak | BlockQuote [r] | CodeBlock Text Text | Heading Int [Inline a] | RawBlock Format Text | ReferenceLinkDefinition Text (Text, Text) | List ListType ListSpacing [[r]] deriving (Show, Eq, Functor, Foldable, Traversable) $(deriveShow1 ''BlockF) $(deriveEq1 ''BlockF) type Block a = Cofree (BlockF a) a pattern MkBlock :: a -> BlockF a (Block a) -> Block a pattern MkBlock a body = a :< body {-# COMPLETE MkBlock #-} type Blocks = [Block Ann] rangedBlock :: SourceRange -> Block Ann -> Block Ann rangedBlock sr (MkBlock ann body) = MkBlock (ann <> MkAnn sr mempty) body addAttributesBlock :: Attributes -> Block Ann -> Block Ann addAttributesBlock attrs (MkBlock ann body) = MkBlock (ann <> MkAnn mempty attrs) body instance Rangeable Blocks where ranged sr = map $ rangedBlock sr instance HasAttributes Blocks where addAttributes attrs = map $ addAttributesBlock attrs mkBlock :: (Monoid a) => BlockF a (Block a) -> Block a mkBlock = MkBlock mempty instance IsBlock Inlines Blocks where paragraph ils = [mkBlock $ Paragraph ils] plain ils = [mkBlock $ Plain ils] thematicBreak = [mkBlock ThematicBreak] blockQuote bs = [mkBlock $ BlockQuote bs] codeBlock info c = [mkBlock $ CodeBlock info c] heading level ils = [mkBlock $ Heading level ils] rawBlock f t = [mkBlock $ RawBlock f t] referenceLinkDefinition l dt = [mkBlock $ ReferenceLinkDefinition l dt] list lt ls bss = [mkBlock $ List lt ls bss]