notion-client-0.1.0.0: src/Notion/V1/RichText.hs
-- | Rich Text objects in Notion API
module Notion.V1.RichText
( -- * Rich Text types
RichText (..),
RichTextContent (..),
TextContent (..),
MentionContent (..),
EquationContent (..),
Annotations (..),
defaultAnnotations,
Link (..),
Date (..),
TimeZone (..),
)
where
import Data.Aeson (object, (.:), (.:?), (.=))
import Notion.Prelude
import Notion.V1.Common (Color (..), UUID)
-- | Rich text object in Notion
data RichText = RichText
{ plainText :: Text,
href :: Maybe Text,
annotations :: Annotations,
type_ :: Text,
content :: RichTextContent
}
deriving stock (Generic, Show)
instance FromJSON RichText where
parseJSON = \case
Object o -> do
plainText <- o .: "plain_text"
href <- o .:? "href"
annotations <- o .: "annotations"
type_ <- o .: "type"
content <- case type_ of
"text" -> TextContentWrapper <$> o .: "text"
"mention" -> MentionContentWrapper <$> o .: "mention"
"equation" -> EquationContentWrapper <$> o .: "equation"
other -> fail $ "Unknown rich text type: " <> unpack other
return RichText {..}
_ -> fail "Expected object for RichText"
instance ToJSON RichText where
toJSON RichText {..} =
object $
[ "type" .= type_,
"plain_text" .= plainText,
"annotations" .= annotations
]
++ maybe [] (\h -> ["href" .= h]) href
++ case content of
TextContentWrapper tc -> ["text" .= tc]
MentionContentWrapper mc -> ["mention" .= mc]
EquationContentWrapper ec -> ["equation" .= ec]
-- | Text content
data TextContent = TextContent
{ content :: Text,
link :: Maybe Link
}
deriving stock (Generic, Show)
instance FromJSON TextContent where
parseJSON = genericParseJSON aesonOptions
instance ToJSON TextContent where
toJSON = genericToJSON aesonOptions
-- | Mention content
--
-- Notion mentions have a @type@ discriminator and the content nested under
-- the corresponding field name. For example:
--
-- @
-- { "type": "user", "user": { "id": "..." } }
-- @
data MentionContent
= UserMention {user :: UUID}
| PageMention {page :: UUID}
| DatabaseMention {database :: UUID}
| DateMention {date :: Date}
| LinkPreviewMention {url :: Text}
deriving stock (Generic, Show)
instance FromJSON MentionContent where
parseJSON = \case
Object o -> do
mentionType <- o .: "type"
case mentionType of
"user" -> do
userObj <- o .: "user"
UserMention <$> parseIdField userObj
"page" -> do
pageObj <- o .: "page"
PageMention <$> parseIdField pageObj
"database" -> do
dbObj <- o .: "database"
DatabaseMention <$> parseIdField dbObj
"date" -> DateMention <$> o .: "date"
"link_preview" -> do
lpObj <- o .: "link_preview"
LinkPreviewMention <$> parseUrlField lpObj
other -> fail $ "Unknown mention type: " <> unpack other
_ -> fail "Expected object for MentionContent"
where
parseIdField = \case
Object o -> o .: "id"
_ -> fail "Expected object with id field"
parseUrlField = \case
Object o -> o .: "url"
_ -> fail "Expected object with url field"
instance ToJSON MentionContent where
toJSON = \case
UserMention uid ->
object ["type" .= ("user" :: Text), "user" .= object ["id" .= uid]]
PageMention pid ->
object ["type" .= ("page" :: Text), "page" .= object ["id" .= pid]]
DatabaseMention dbid ->
object ["type" .= ("database" :: Text), "database" .= object ["id" .= dbid]]
DateMention d ->
object ["type" .= ("date" :: Text), "date" .= d]
LinkPreviewMention u ->
object ["type" .= ("link_preview" :: Text), "link_preview" .= object ["url" .= u]]
-- | Equation content
newtype EquationContent = EquationContent
{ expression :: Text
}
deriving stock (Generic, Show)
instance FromJSON EquationContent where
parseJSON = genericParseJSON aesonOptions
instance ToJSON EquationContent where
toJSON = genericToJSON aesonOptions
-- | Content of a rich text object
data RichTextContent
= TextContentWrapper TextContent
| MentionContentWrapper MentionContent
| EquationContentWrapper EquationContent
deriving stock (Generic, Show)
-- | Text annotations
data Annotations = Annotations
{ bold :: Bool,
italic :: Bool,
strikethrough :: Bool,
underline :: Bool,
code :: Bool,
color :: Color
}
deriving stock (Generic, Show)
instance FromJSON Annotations where
parseJSON = genericParseJSON aesonOptions
instance ToJSON Annotations where
toJSON = genericToJSON aesonOptions
-- | Default annotations
defaultAnnotations :: Annotations
defaultAnnotations =
Annotations
{ bold = False,
italic = False,
strikethrough = False,
underline = False,
code = False,
color = Default
}
-- | Link object
newtype Link = Link
{ url :: Text
}
deriving stock (Generic, Show)
instance FromJSON Link where
parseJSON = genericParseJSON aesonOptions
instance ToJSON Link where
toJSON = genericToJSON aesonOptions
-- | Date object
data Date = Date
{ start :: Text,
end :: Maybe Text,
timeZone :: Maybe TimeZone
}
deriving stock (Generic, Show)
instance FromJSON Date where
parseJSON = genericParseJSON aesonOptions
instance ToJSON Date where
toJSON = genericToJSON aesonOptions
-- | Time zone
newtype TimeZone = TimeZone
{ text :: Text
}
deriving newtype (FromJSON, IsString, Show, ToJSON)