{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveFoldable #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ViewPatterns #-} -- | A definition of Commonmark's AST module Text.Commonmark.Syntax ( Doc(..) -- * Block Elements , Blocks , Block(..) , HeadingLevel(..) , ListType(..) , Delimiter(..) , BulletMarker(..) -- * Inline Elements , Inlines , Inline(..) , normalize , asText ) where import Control.DeepSeq (NFData) import Data.Data (Data, Typeable) import Data.Monoid import Data.Sequence (Seq, ViewL(..), viewl, (<|)) import Data.String (IsString(..)) import GHC.Generics (Generic) -- | A Document newtype Doc t = Doc (Blocks t) deriving ( Show, Read, Eq , Typeable, Data, Generic , Functor, Foldable, Traversable ) instance NFData t => NFData (Doc t) instance Monoid t => Monoid (Doc t) where mempty = Doc mempty (Doc bs1 ) `mappend` (Doc bs2) = Doc (bs1 `mappend` bs2) type Blocks t = Seq (Block t) -- | Block elements data Block t -- | Thematic break = ThematicBreak -- | Heading: level, sequnce of inlines that define content | Heading HeadingLevel (Inlines t) -- | Block of code: info string, literal content | CodeBlock (Maybe t) t -- | Raw HTML Block | HtmlBlock t -- | Paragraph (a grouped sequence of inlines) | Para (Inlines t) -- | Block Quote (a quoted sequence of blocks) | Quote (Blocks t) -- | List: Type of the list, tightness, a sequnce of blocks (list item) | List ListType Bool (Seq (Blocks t)) deriving ( Show, Read, Eq, Ord , Typeable, Data, Generic , Functor, Foldable, Traversable ) instance (NFData t) => NFData (Block t) data HeadingLevel = Heading1 | Heading2 | Heading3 | Heading4 | Heading5 | Heading6 deriving ( Show, Read, Eq, Ord , Typeable, Data, Generic ) instance NFData HeadingLevel data ListType = Ordered Delimiter Int | Bullet BulletMarker deriving ( Show, Read, Eq, Ord , Typeable, Data, Generic ) instance NFData ListType data Delimiter = Period | Paren deriving ( Show, Read, Eq, Ord , Typeable, Data, Generic ) instance NFData Delimiter data BulletMarker = Minus -- ^ @-@ | Plus -- ^ @+@ | Asterisk -- ^ @*@ deriving ( Show, Read, Eq, Ord , Typeable, Data, Generic ) instance NFData BulletMarker type Inlines t = Seq (Inline t) -- | Inline elements data Inline t -- | Text (string) = Str t -- | Inline code | Code t -- | Emphasized text (a sequence of inlines) | Emph (Inlines t) -- | Strongly emphasized text (a sequence of inlines) | Strong (Inlines t) -- | Hyperlink: visible link text (sequence of inlines), destination, title | Link (Inlines t) t (Maybe t) -- TODO: special types -- | Image hyperlink: image description, destination, title | Image (Inlines t) t (Maybe t) -- TODO: special types -- | Inline Raw HTML tag | RawHtml t -- | A regular linebreak. A conforming renderer may render a soft -- line break in HTML either as line break or as a space. | SoftBreak -- | A line break that is marked as hard (either with spaces or -- backslash, see the spec for details). In html it would be rendered -- as @
@ | HardBreak deriving ( Show, Read, Eq, Ord , Typeable, Data, Generic , Functor, Foldable, Traversable ) instance IsString t => IsString (Inline t) where fromString = Str . fromString instance NFData t => NFData (Inline t) -- | Consolidate adjacent text nodes normalize :: Monoid t => Inlines t -> Inlines t normalize inlines = case viewl inlines of Str t :< (viewl -> Str ts :< is) -> normalize (Str (t <> ts) <| is) Image i u t :< is -> Image (normalize i) u t <| normalize is Link i u t :< is -> Link (normalize i) u t <| normalize is Emph i :< is -> Emph (normalize i) <| normalize is Strong i :< is -> Strong (normalize i) <| normalize is i :< is -> i <| normalize is EmptyL -> mempty -- | Extract textual content from an inline. -- Note that it extracts only the 'primary' content (the one that is shown in -- first place). For example it wouldn't extract an URL from the link. asText :: (Monoid a, IsString a) => Inline a -> a asText (Str t) = t asText (Emph is) = foldMap asText is asText (Strong is) = foldMap asText is asText (Code t) = t asText (Link is _ _) = foldMap asText is asText (Image is _ _) = foldMap asText is asText (RawHtml t) = t asText SoftBreak = " " asText HardBreak = "\n"