{-# LANGUAGE CPP                        #-}
{-# LANGUAGE DeriveGeneric              #-}
{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE NoImplicitPrelude          #-}
{-# LANGUAGE OverloadedStrings          #-}
{-# LANGUAGE ScopedTypeVariables        #-}
{- |
   Module      : Data.Ipynb
   Copyright   : Copyright (C) 2019 John MacFarlane
   License     : BSD3

   Maintainer  : John MacFarlane <jgm@berkeley.edu>
   Stability   : alpha
   Portability : portable

Data structure and JSON serializers for ipynb (Jupyter notebook) format.
Version 4 of the format is documented here:
<https://nbformat.readthedocs.io/en/latest/format_description.html>.

The library supports both version 4 ('Notebook NbV4') and version 3
('Notebook NbV3') of nbformat.  Note that this is a phantom type: the
`NbV3` or `NbV4` parameter only affects JSON serialization,
not the data structure itself.  So code that manipulates
notebooks can be polymorphic, operating on `Notebook a`.

-}
module Data.Ipynb ( Notebook(..)
                  , NbV3
                  , NbV4
                  , JSONMeta(..)
                  , Cell(..)
                  , Source(..)
                  , CellType(..)
                  , Output(..)
                  , MimeType
                  , MimeData(..)
                  , MimeBundle(..)
                  , MimeAttachments(..)
                  , breakLines
                  )
where
import Control.Applicative ((<|>))
import Control.Monad (when)
import Data.Aeson as Aeson
import qualified Data.Aeson.Types as Aeson
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import qualified Data.ByteString.Base64 as Base64
import Data.Char (isSpace)
import Data.List (partition, sortOn)
import qualified Data.Map as M
import Data.Maybe (mapMaybe)
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import GHC.Generics
import Prelude
#if MIN_VERSION_base(4,11,0)
#else
import Data.Semigroup
#endif
#if MIN_VERSION_aeson(2,0,0)
import qualified Data.Aeson.KeyMap as KM
#else
import qualified Data.HashMap.Strict as KM
#endif
import Data.String
import qualified Data.Set as Set

-- | Indexes 'Notebook' for serialization as nbformat version 3.
data NbV3

-- | Indexes 'Notebook' for serialization as nbformat version 4.
data NbV4

-- | A Jupyter notebook.
data Notebook a = Notebook
  { forall a. Notebook a -> JSONMeta
notebookMetadata :: JSONMeta
  , forall a. Notebook a -> (Int, Int)
notebookFormat   :: (Int, Int)
  , forall a. Notebook a -> [Cell a]
notebookCells    :: [Cell a]
  } deriving (Int -> Notebook a -> ShowS
forall a. Int -> Notebook a -> ShowS
forall a. [Notebook a] -> ShowS
forall a. Notebook a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Notebook a] -> ShowS
$cshowList :: forall a. [Notebook a] -> ShowS
show :: Notebook a -> String
$cshow :: forall a. Notebook a -> String
showsPrec :: Int -> Notebook a -> ShowS
$cshowsPrec :: forall a. Int -> Notebook a -> ShowS
Show, Notebook a -> Notebook a -> Bool
forall a. Notebook a -> Notebook a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Notebook a -> Notebook a -> Bool
$c/= :: forall a. Notebook a -> Notebook a -> Bool
== :: Notebook a -> Notebook a -> Bool
$c== :: forall a. Notebook a -> Notebook a -> Bool
Eq, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Notebook a) x -> Notebook a
forall a x. Notebook a -> Rep (Notebook a) x
$cto :: forall a x. Rep (Notebook a) x -> Notebook a
$cfrom :: forall a x. Notebook a -> Rep (Notebook a) x
Generic)

instance Semigroup (Notebook a) where
  Notebook JSONMeta
m1 (Int, Int)
f1 [Cell a]
c1 <> :: Notebook a -> Notebook a -> Notebook a
<> Notebook JSONMeta
m2 (Int, Int)
f2 [Cell a]
c2 =
    forall a. JSONMeta -> (Int, Int) -> [Cell a] -> Notebook a
Notebook (JSONMeta
m1 forall a. Semigroup a => a -> a -> a
<> JSONMeta
m2) (forall a. Ord a => a -> a -> a
max (Int, Int)
f1 (Int, Int)
f2) ([Cell a]
c1 forall a. Semigroup a => a -> a -> a
<> [Cell a]
c2)

instance Monoid (Notebook a) where
  mempty :: Notebook a
mempty = forall a. JSONMeta -> (Int, Int) -> [Cell a] -> Notebook a
Notebook forall a. Monoid a => a
mempty (Int
0, Int
0) forall a. Monoid a => a
mempty
#if MIN_VERSION_base(4,11,0)
#else
  mappend = (<>)
#endif

instance FromJSON (Notebook NbV4) where
  parseJSON :: Value -> Parser (Notebook NbV4)
parseJSON = forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"Notebook" forall a b. (a -> b) -> a -> b
$ \Object
v -> do
    Int
fmt <- Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"nbformat" forall a. Parser (Maybe a) -> a -> Parser a
.!= Int
0
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
fmt forall a. Ord a => a -> a -> Bool
< Int
4 Bool -> Bool -> Bool
|| Int
fmt forall a. Ord a => a -> a -> Bool
> Int
4) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"expected nbformat == 4"
    Int
fmtminor <- Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"nbformat_minor" forall a. Parser (Maybe a) -> a -> Parser a
.!= Int
0
    JSONMeta
metadata <- Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"metadata" forall a. Parser (Maybe a) -> a -> Parser a
.!= forall a. Monoid a => a
mempty
    [Cell NbV4]
cells <- Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"cells"
    forall (m :: * -> *) a. Monad m => a -> m a
return
      Notebook{ notebookMetadata :: JSONMeta
notebookMetadata = JSONMeta
metadata
              , notebookFormat :: (Int, Int)
notebookFormat = (Int
fmt, Int
fmtminor)
              , notebookCells :: [Cell NbV4]
notebookCells    = [Cell NbV4]
cells
              }

instance FromJSON (Notebook NbV3) where
  parseJSON :: Value -> Parser (Notebook NbV3)
parseJSON = forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"Notebook" forall a b. (a -> b) -> a -> b
$ \Object
v -> do
    Int
fmt <- Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"nbformat" forall a. Parser (Maybe a) -> a -> Parser a
.!= Int
0
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
fmt forall a. Ord a => a -> a -> Bool
> Int
3) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"expected nbformat <= 3"
    Int
fmtminor <- Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"nbformat_minor" forall a. Parser (Maybe a) -> a -> Parser a
.!= Int
0
    JSONMeta
metadata <- Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"metadata" forall a. Parser (Maybe a) -> a -> Parser a
.!= forall a. Monoid a => a
mempty
    [Object]
worksheets <- Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"worksheets"
    -- NOTE: we ignore metadata on worksheets: is this ever used?
    [Cell NbV3]
cells <- forall a. Monoid a => [a] -> a
mconcat forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"cells") [Object]
worksheets
    forall (m :: * -> *) a. Monad m => a -> m a
return
      Notebook{ notebookMetadata :: JSONMeta
notebookMetadata = JSONMeta
metadata
              , notebookFormat :: (Int, Int)
notebookFormat = (Int
fmt, Int
fmtminor)
              , notebookCells :: [Cell NbV3]
notebookCells = [Cell NbV3]
cells
              }

instance ToJSON (Notebook NbV4) where
 toJSON :: Notebook NbV4 -> Value
toJSON Notebook NbV4
n = [Pair] -> Value
object
   [ Key
"nbformat" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a b. (a, b) -> a
fst (forall a. Notebook a -> (Int, Int)
notebookFormat Notebook NbV4
n)
   , Key
"nbformat_minor" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a b. (a, b) -> b
snd (forall a. Notebook a -> (Int, Int)
notebookFormat Notebook NbV4
n)
   , Key
"metadata" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Notebook a -> JSONMeta
notebookMetadata Notebook NbV4
n
   , Key
"cells" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= (if forall a. Notebook a -> (Int, Int)
notebookFormat Notebook NbV4
n forall a. Ord a => a -> a -> Bool
>= (Int
4,Int
1)
                    then forall a. a -> a
id
                    else forall a b. (a -> b) -> [a] -> [b]
map (\Cell NbV4
c -> Cell NbV4
c{ cellAttachments :: Maybe MimeAttachments
cellAttachments = forall a. Maybe a
Nothing }))
                (forall a. Notebook a -> [Cell a]
notebookCells Notebook NbV4
n)
   ]

instance ToJSON (Notebook NbV3) where
 toJSON :: Notebook NbV3 -> Value
toJSON Notebook NbV3
n = [Pair] -> Value
object
   [ Key
"nbformat" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a b. (a, b) -> a
fst (forall a. Notebook a -> (Int, Int)
notebookFormat Notebook NbV3
n)
   , Key
"nbformat_minor" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a b. (a, b) -> b
snd (forall a. Notebook a -> (Int, Int)
notebookFormat Notebook NbV3
n)
   , Key
"metadata" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Notebook a -> JSONMeta
notebookMetadata Notebook NbV3
n
   , Key
"worksheets" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.=
     [ [Pair] -> Value
object
       [ Key
"cells" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= (if forall a. Notebook a -> (Int, Int)
notebookFormat Notebook NbV3
n forall a. Ord a => a -> a -> Bool
>= (Int
4,Int
1)
                        then forall a. a -> a
id
                        else forall a b. (a -> b) -> [a] -> [b]
map (\Cell NbV3
c -> Cell NbV3
c{ cellAttachments :: Maybe MimeAttachments
cellAttachments = forall a. Maybe a
Nothing }))
                    (forall a. Notebook a -> [Cell a]
notebookCells Notebook NbV3
n)
       , Key
"metadata" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= (forall a. Monoid a => a
mempty :: JSONMeta) -- see above in FromJSON instance
       ]
     ]
   ]

newtype JSONMeta = JSONMeta (M.Map Text Value)
  deriving (Int -> JSONMeta -> ShowS
[JSONMeta] -> ShowS
JSONMeta -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [JSONMeta] -> ShowS
$cshowList :: [JSONMeta] -> ShowS
show :: JSONMeta -> String
$cshow :: JSONMeta -> String
showsPrec :: Int -> JSONMeta -> ShowS
$cshowsPrec :: Int -> JSONMeta -> ShowS
Show, JSONMeta -> JSONMeta -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: JSONMeta -> JSONMeta -> Bool
$c/= :: JSONMeta -> JSONMeta -> Bool
== :: JSONMeta -> JSONMeta -> Bool
$c== :: JSONMeta -> JSONMeta -> Bool
Eq, Eq JSONMeta
JSONMeta -> JSONMeta -> Bool
JSONMeta -> JSONMeta -> Ordering
JSONMeta -> JSONMeta -> JSONMeta
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: JSONMeta -> JSONMeta -> JSONMeta
$cmin :: JSONMeta -> JSONMeta -> JSONMeta
max :: JSONMeta -> JSONMeta -> JSONMeta
$cmax :: JSONMeta -> JSONMeta -> JSONMeta
>= :: JSONMeta -> JSONMeta -> Bool
$c>= :: JSONMeta -> JSONMeta -> Bool
> :: JSONMeta -> JSONMeta -> Bool
$c> :: JSONMeta -> JSONMeta -> Bool
<= :: JSONMeta -> JSONMeta -> Bool
$c<= :: JSONMeta -> JSONMeta -> Bool
< :: JSONMeta -> JSONMeta -> Bool
$c< :: JSONMeta -> JSONMeta -> Bool
compare :: JSONMeta -> JSONMeta -> Ordering
$ccompare :: JSONMeta -> JSONMeta -> Ordering
Ord, forall x. Rep JSONMeta x -> JSONMeta
forall x. JSONMeta -> Rep JSONMeta x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep JSONMeta x -> JSONMeta
$cfrom :: forall x. JSONMeta -> Rep JSONMeta x
Generic, NonEmpty JSONMeta -> JSONMeta
JSONMeta -> JSONMeta -> JSONMeta
forall b. Integral b => b -> JSONMeta -> JSONMeta
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: forall b. Integral b => b -> JSONMeta -> JSONMeta
$cstimes :: forall b. Integral b => b -> JSONMeta -> JSONMeta
sconcat :: NonEmpty JSONMeta -> JSONMeta
$csconcat :: NonEmpty JSONMeta -> JSONMeta
<> :: JSONMeta -> JSONMeta -> JSONMeta
$c<> :: JSONMeta -> JSONMeta -> JSONMeta
Semigroup, Semigroup JSONMeta
JSONMeta
[JSONMeta] -> JSONMeta
JSONMeta -> JSONMeta -> JSONMeta
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [JSONMeta] -> JSONMeta
$cmconcat :: [JSONMeta] -> JSONMeta
mappend :: JSONMeta -> JSONMeta -> JSONMeta
$cmappend :: JSONMeta -> JSONMeta -> JSONMeta
mempty :: JSONMeta
$cmempty :: JSONMeta
Monoid, Value -> Parser [JSONMeta]
Value -> Parser JSONMeta
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [JSONMeta]
$cparseJSONList :: Value -> Parser [JSONMeta]
parseJSON :: Value -> Parser JSONMeta
$cparseJSON :: Value -> Parser JSONMeta
FromJSON)

instance ToJSON JSONMeta where
   toJSON :: JSONMeta -> Value
toJSON = forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON Options
defaultOptions
   toEncoding :: JSONMeta -> Encoding
toEncoding = forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
genericToEncoding Options
defaultOptions

-- | A 'Source' is a textual content which may be
-- represented in JSON either as a single string
-- or as a list of strings (which are concatenated).
newtype Source = Source{ Source -> [Text]
unSource :: [Text] }
  deriving (Int -> Source -> ShowS
[Source] -> ShowS
Source -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Source] -> ShowS
$cshowList :: [Source] -> ShowS
show :: Source -> String
$cshow :: Source -> String
showsPrec :: Int -> Source -> ShowS
$cshowsPrec :: Int -> Source -> ShowS
Show, Source -> Source -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Source -> Source -> Bool
$c/= :: Source -> Source -> Bool
== :: Source -> Source -> Bool
$c== :: Source -> Source -> Bool
Eq, forall x. Rep Source x -> Source
forall x. Source -> Rep Source x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Source x -> Source
$cfrom :: forall x. Source -> Rep Source x
Generic, NonEmpty Source -> Source
Source -> Source -> Source
forall b. Integral b => b -> Source -> Source
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: forall b. Integral b => b -> Source -> Source
$cstimes :: forall b. Integral b => b -> Source -> Source
sconcat :: NonEmpty Source -> Source
$csconcat :: NonEmpty Source -> Source
<> :: Source -> Source -> Source
$c<> :: Source -> Source -> Source
Semigroup, Semigroup Source
Source
[Source] -> Source
Source -> Source -> Source
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [Source] -> Source
$cmconcat :: [Source] -> Source
mappend :: Source -> Source -> Source
$cmappend :: Source -> Source -> Source
mempty :: Source
$cmempty :: Source
Monoid)

instance FromJSON Source where
  parseJSON :: Value -> Parser Source
parseJSON Value
v = do
    [Text]
ts <- forall a. FromJSON a => Value -> Parser a
parseJSON Value
v forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (forall a. a -> [a] -> [a]
:[]) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromJSON a => Value -> Parser a
parseJSON Value
v
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ [Text] -> Source
Source [Text]
ts

instance ToJSON Source where
  toJSON :: Source -> Value
toJSON (Source [Text]
ts) = forall a. ToJSON a => a -> Value
toJSON [Text]
ts

newtype MimeAttachments = MimeAttachments (M.Map Text MimeBundle)
  deriving (Int -> MimeAttachments -> ShowS
[MimeAttachments] -> ShowS
MimeAttachments -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MimeAttachments] -> ShowS
$cshowList :: [MimeAttachments] -> ShowS
show :: MimeAttachments -> String
$cshow :: MimeAttachments -> String
showsPrec :: Int -> MimeAttachments -> ShowS
$cshowsPrec :: Int -> MimeAttachments -> ShowS
Show, MimeAttachments -> MimeAttachments -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MimeAttachments -> MimeAttachments -> Bool
$c/= :: MimeAttachments -> MimeAttachments -> Bool
== :: MimeAttachments -> MimeAttachments -> Bool
$c== :: MimeAttachments -> MimeAttachments -> Bool
Eq, Eq MimeAttachments
MimeAttachments -> MimeAttachments -> Bool
MimeAttachments -> MimeAttachments -> Ordering
MimeAttachments -> MimeAttachments -> MimeAttachments
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: MimeAttachments -> MimeAttachments -> MimeAttachments
$cmin :: MimeAttachments -> MimeAttachments -> MimeAttachments
max :: MimeAttachments -> MimeAttachments -> MimeAttachments
$cmax :: MimeAttachments -> MimeAttachments -> MimeAttachments
>= :: MimeAttachments -> MimeAttachments -> Bool
$c>= :: MimeAttachments -> MimeAttachments -> Bool
> :: MimeAttachments -> MimeAttachments -> Bool
$c> :: MimeAttachments -> MimeAttachments -> Bool
<= :: MimeAttachments -> MimeAttachments -> Bool
$c<= :: MimeAttachments -> MimeAttachments -> Bool
< :: MimeAttachments -> MimeAttachments -> Bool
$c< :: MimeAttachments -> MimeAttachments -> Bool
compare :: MimeAttachments -> MimeAttachments -> Ordering
$ccompare :: MimeAttachments -> MimeAttachments -> Ordering
Ord, forall x. Rep MimeAttachments x -> MimeAttachments
forall x. MimeAttachments -> Rep MimeAttachments x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep MimeAttachments x -> MimeAttachments
$cfrom :: forall x. MimeAttachments -> Rep MimeAttachments x
Generic, NonEmpty MimeAttachments -> MimeAttachments
MimeAttachments -> MimeAttachments -> MimeAttachments
forall b. Integral b => b -> MimeAttachments -> MimeAttachments
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: forall b. Integral b => b -> MimeAttachments -> MimeAttachments
$cstimes :: forall b. Integral b => b -> MimeAttachments -> MimeAttachments
sconcat :: NonEmpty MimeAttachments -> MimeAttachments
$csconcat :: NonEmpty MimeAttachments -> MimeAttachments
<> :: MimeAttachments -> MimeAttachments -> MimeAttachments
$c<> :: MimeAttachments -> MimeAttachments -> MimeAttachments
Semigroup, Semigroup MimeAttachments
MimeAttachments
[MimeAttachments] -> MimeAttachments
MimeAttachments -> MimeAttachments -> MimeAttachments
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [MimeAttachments] -> MimeAttachments
$cmconcat :: [MimeAttachments] -> MimeAttachments
mappend :: MimeAttachments -> MimeAttachments -> MimeAttachments
$cmappend :: MimeAttachments -> MimeAttachments -> MimeAttachments
mempty :: MimeAttachments
$cmempty :: MimeAttachments
Monoid, Value -> Parser [MimeAttachments]
Value -> Parser MimeAttachments
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [MimeAttachments]
$cparseJSONList :: Value -> Parser [MimeAttachments]
parseJSON :: Value -> Parser MimeAttachments
$cparseJSON :: Value -> Parser MimeAttachments
FromJSON)

instance ToJSON MimeAttachments where
   toJSON :: MimeAttachments -> Value
toJSON = forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON Options
defaultOptions
   toEncoding :: MimeAttachments -> Encoding
toEncoding = forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
genericToEncoding Options
defaultOptions

-- | A Jupyter notebook cell.
data Cell a = Cell
  { forall a. Cell a -> CellType a
cellType        :: CellType a
  , forall a. Cell a -> Maybe Text
cellId          :: Maybe Text
  , forall a. Cell a -> Source
cellSource      :: Source
  , forall a. Cell a -> JSONMeta
cellMetadata    :: JSONMeta
  , forall a. Cell a -> Maybe MimeAttachments
cellAttachments :: Maybe MimeAttachments
} deriving (Int -> Cell a -> ShowS
forall a. Int -> Cell a -> ShowS
forall a. [Cell a] -> ShowS
forall a. Cell a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Cell a] -> ShowS
$cshowList :: forall a. [Cell a] -> ShowS
show :: Cell a -> String
$cshow :: forall a. Cell a -> String
showsPrec :: Int -> Cell a -> ShowS
$cshowsPrec :: forall a. Int -> Cell a -> ShowS
Show, Cell a -> Cell a -> Bool
forall a. Cell a -> Cell a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Cell a -> Cell a -> Bool
$c/= :: forall a. Cell a -> Cell a -> Bool
== :: Cell a -> Cell a -> Bool
$c== :: forall a. Cell a -> Cell a -> Bool
Eq, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Cell a) x -> Cell a
forall a x. Cell a -> Rep (Cell a) x
$cto :: forall a x. Rep (Cell a) x -> Cell a
$cfrom :: forall a x. Cell a -> Rep (Cell a) x
Generic)

instance FromJSON (Cell NbV4) where
  parseJSON :: Value -> Parser (Cell NbV4)
parseJSON = forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"Cell" forall a b. (a -> b) -> a -> b
$ \Object
v -> do
    String
ty <- Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"cell_type"
    Maybe Text
cell_id <- Object
vforall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"id"
    CellType NbV4
cell_type <-
      case String
ty of
        String
"markdown" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. CellType a
Markdown
        String
"raw" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. CellType a
Raw
        String
"code" ->
          forall a. Maybe Int -> [Output a] -> CellType a
Code
            forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"execution_count"
            forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"outputs"
        String
_ -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"Unknown cell_type " forall a. [a] -> [a] -> [a]
++ String
ty
    JSONMeta
metadata <- Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"metadata"
    Maybe MimeAttachments
attachments <- Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"attachments"
    Source
source <- Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"source"
    forall (m :: * -> *) a. Monad m => a -> m a
return
      Cell{ cellType :: CellType NbV4
cellType = CellType NbV4
cell_type
          , cellId :: Maybe Text
cellId = Maybe Text
cell_id
          , cellMetadata :: JSONMeta
cellMetadata = JSONMeta
metadata
          , cellAttachments :: Maybe MimeAttachments
cellAttachments = Maybe MimeAttachments
attachments
          , cellSource :: Source
cellSource = Source
source
          }

instance FromJSON (Cell NbV3) where
  parseJSON :: Value -> Parser (Cell NbV3)
parseJSON = forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"Cell" forall a b. (a -> b) -> a -> b
$ \Object
v -> do
    String
ty <- Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"cell_type"
    CellType NbV3
cell_type <-
      case String
ty of
        String
"markdown" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. CellType a
Markdown
        String
"heading" -> forall a. Int -> CellType a
Heading forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"level"
        String
"raw" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. CellType a
Raw
        String
"code" ->
          forall a. Maybe Int -> [Output a] -> CellType a
Code
            forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"prompt_number"
            forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"outputs"
        String
_ -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"Unknown cell_type " forall a. [a] -> [a] -> [a]
++ String
ty
    JSONMeta
metadata <- Object -> Parser JSONMeta
parseV3Metadata Object
v
    Source
source <- if String
ty forall a. Eq a => a -> a -> Bool
== String
"code"
                 then Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"input"
                 else Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"source"
    forall (m :: * -> *) a. Monad m => a -> m a
return
      Cell{ cellType :: CellType NbV3
cellType = CellType NbV3
cell_type
          , cellId :: Maybe Text
cellId = forall a. Maybe a
Nothing
          , cellMetadata :: JSONMeta
cellMetadata = JSONMeta
metadata
          , cellAttachments :: Maybe MimeAttachments
cellAttachments = forall a. Maybe a
Nothing
          , cellSource :: Source
cellSource = Source
source
          }

-- note that execution_count can't be omitted!
instance ToJSON (Cell NbV4) where
 toJSON :: Cell NbV4 -> Value
toJSON Cell NbV4
c = [Pair] -> Value
object forall a b. (a -> b) -> a -> b
$
   (Key
"metadata" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Cell a -> JSONMeta
cellMetadata Cell NbV4
c) forall a. a -> [a] -> [a]
:
   forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (\Text
x -> [Key
"id" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Cell a -> Maybe Text
cellId Cell NbV4
c]) (forall a. Cell a -> Maybe Text
cellId Cell NbV4
c) forall a. [a] -> [a] -> [a]
++
   forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (\MimeAttachments
x -> [Key
"attachments" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= MimeAttachments
x]) (forall a. Cell a -> Maybe MimeAttachments
cellAttachments Cell NbV4
c) forall a. [a] -> [a] -> [a]
++
   case forall a. Cell a -> CellType a
cellType Cell NbV4
c of
     CellType NbV4
Markdown -> [ Key
"cell_type" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= (Text
"markdown" :: Text)
                 , Key
"source" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Cell a -> Source
cellSource Cell NbV4
c ]
     Heading Int
lev ->
                [ Key
"cell_type" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= (Text
"markdown" :: Text)
                , Key
"source" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.=
                     ([Text] -> Source
Source forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text]
breakLines forall b c a. (b -> c) -> (a -> b) -> a -> c
.
                      ((Int -> Text -> Text
T.replicate Int
lev Text
"#" forall a. Semigroup a => a -> a -> a
<> Text
" ") forall a. Semigroup a => a -> a -> a
<>) forall b c a. (b -> c) -> (a -> b) -> a -> c
.
                      forall a. Monoid a => [a] -> a
mconcat forall b c a. (b -> c) -> (a -> b) -> a -> c
. Source -> [Text]
unSource) (forall a. Cell a -> Source
cellSource Cell NbV4
c)
                 ]
     CellType NbV4
Raw      -> [ Key
"cell_type" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= (Text
"raw" :: Text)
                 , Key
"source" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Cell a -> Source
cellSource Cell NbV4
c
                 ]
     Code{
         codeExecutionCount :: forall a. CellType a -> Maybe Int
codeExecutionCount = Maybe Int
ec
       , codeOutputs :: forall a. CellType a -> [Output a]
codeOutputs = [Output NbV4]
outs
       }      -> [ Key
"cell_type" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= (Text
"code" :: Text)
                 , Key
"execution_count" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Int
ec
                 , Key
"outputs" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= [Output NbV4]
outs
                 , Key
"source" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Cell a -> Source
cellSource Cell NbV4
c
                 ]

instance ToJSON (Cell NbV3) where
 toJSON :: Cell NbV3 -> Value
toJSON Cell NbV3
c =
  [Pair] -> Value
object forall a b. (a -> b) -> a -> b
$
   JSONMeta -> [Pair]
metadataToV3Pairs (forall a. Cell a -> JSONMeta
cellMetadata Cell NbV3
c) forall a. [a] -> [a] -> [a]
++
   case forall a. Cell a -> CellType a
cellType Cell NbV3
c of
     CellType NbV3
Markdown    -> [ Key
"cell_type" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= (Text
"markdown" :: Text)
                    , Key
"source" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Cell a -> Source
cellSource Cell NbV3
c
                    ]
     Heading Int
lev -> [ Key
"cell_type" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= (Text
"heading" :: Text)
                    , Key
"level" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Int
lev
                    , Key
"source" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Cell a -> Source
cellSource Cell NbV3
c
                    ]
     CellType NbV3
Raw         -> [ Key
"cell_type" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= (Text
"raw" :: Text)
                    , Key
"source" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Cell a -> Source
cellSource Cell NbV3
c
                    ]
     Code{
         codeExecutionCount :: forall a. CellType a -> Maybe Int
codeExecutionCount = Maybe Int
ec
       , codeOutputs :: forall a. CellType a -> [Output a]
codeOutputs = [Output NbV3]
outs
       }      -> [ Key
"cell_type" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= (Text
"code" :: Text)
                 , Key
"input" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Cell a -> Source
cellSource Cell NbV3
c
                 , Key
"outputs" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= [Output NbV3]
outs
                 ] forall a. [a] -> [a] -> [a]
++
                 forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (\Int
n -> [Key
"prompt_number" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Int
n]) Maybe Int
ec

-- in v3, certain metadata fields occur in the main cell object.
-- e.g. collapsed, language.
metadataToV3Pairs :: JSONMeta -> [Aeson.Pair]
metadataToV3Pairs :: JSONMeta -> [Pair]
metadataToV3Pairs (JSONMeta Map Text Value
meta) =
  (Key
"metadata" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Map Text Value -> JSONMeta
JSONMeta (forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [(Text, Value)]
regMeta)) forall a. a -> [a] -> [a]
: forall a b. (a -> b) -> [a] -> [b]
map forall {kv} {v}. (KeyValue kv, ToJSON v) => (Text, v) -> kv
toPair [(Text, Value)]
extraMeta
  where ([(Text, Value)]
extraMeta, [(Text, Value)]
regMeta) = forall a. (a -> Bool) -> [a] -> ([a], [a])
partition forall {b}. (Text, b) -> Bool
isExtraMeta forall a b. (a -> b) -> a -> b
$ forall k a. Map k a -> [(k, a)]
M.toList Map Text Value
meta
        toPair :: (Text, v) -> kv
toPair (Text
k,v
v) = (forall a. IsString a => String -> a
fromString (Text -> String
T.unpack Text
k)) forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= v
v
        isExtraMeta :: (Text, b) -> Bool
isExtraMeta (Text
k,b
_) = Text
k forall a. Ord a => a -> Set a -> Bool
`Set.member` Set Text
v3MetaInMainCell

v3MetaInMainCell :: Set.Set Text
v3MetaInMainCell :: Set Text
v3MetaInMainCell = forall a. Ord a => [a] -> Set a
Set.fromList [Text
"collapsed", Text
"language"]

parseV3Metadata :: Aeson.Object -> Aeson.Parser JSONMeta
parseV3Metadata :: Object -> Parser JSONMeta
parseV3Metadata Object
v = do
  JSONMeta
meta <- Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"metadata" forall a. Parser (Maybe a) -> a -> Parser a
.!= forall a. Monoid a => a
mempty
  Map Text Value
vm <- forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
v)
  let extraMeta :: JSONMeta
extraMeta = Map Text Value -> JSONMeta
JSONMeta (forall k a. Ord k => Map k a -> Set k -> Map k a
M.restrictKeys Map Text Value
vm Set Text
v3MetaInMainCell)
  forall (m :: * -> *) a. Monad m => a -> m a
return (JSONMeta
meta forall a. Semigroup a => a -> a -> a
<> JSONMeta
extraMeta)

-- | Information about the type of a notebook cell, plus
-- data specific to that type.  note that 'Heading' is
-- for v3 only; a 'Heading' will be rendered as 'Markdown'
-- in v4.
data CellType a =
    Markdown
  | Heading -- V3 only
    { forall a. CellType a -> Int
headingLevel  :: Int
    }
  | Raw
  | Code
    { forall a. CellType a -> Maybe Int
codeExecutionCount :: Maybe Int
    , forall a. CellType a -> [Output a]
codeOutputs        :: [Output a]
    }
  deriving (Int -> CellType a -> ShowS
forall a. Int -> CellType a -> ShowS
forall a. [CellType a] -> ShowS
forall a. CellType a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CellType a] -> ShowS
$cshowList :: forall a. [CellType a] -> ShowS
show :: CellType a -> String
$cshow :: forall a. CellType a -> String
showsPrec :: Int -> CellType a -> ShowS
$cshowsPrec :: forall a. Int -> CellType a -> ShowS
Show, CellType a -> CellType a -> Bool
forall a. CellType a -> CellType a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CellType a -> CellType a -> Bool
$c/= :: forall a. CellType a -> CellType a -> Bool
== :: CellType a -> CellType a -> Bool
$c== :: forall a. CellType a -> CellType a -> Bool
Eq, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (CellType a) x -> CellType a
forall a x. CellType a -> Rep (CellType a) x
$cto :: forall a x. Rep (CellType a) x -> CellType a
$cfrom :: forall a x. CellType a -> Rep (CellType a) x
Generic)

-- | Output from a Code cell.
data Output a =
    Stream
    { forall a. Output a -> Text
streamName :: Text
    , forall a. Output a -> Source
streamText :: Source }
  | DisplayData
    { forall a. Output a -> MimeBundle
displayData     :: MimeBundle
    , forall a. Output a -> JSONMeta
displayMetadata :: JSONMeta
    }
  | ExecuteResult
    { forall a. Output a -> Int
executeCount    :: Int
    , forall a. Output a -> MimeBundle
executeData     :: MimeBundle
    , forall a. Output a -> JSONMeta
executeMetadata :: JSONMeta
    }
  | Err
    { forall a. Output a -> Text
errName      :: Text
    , forall a. Output a -> Text
errValue     :: Text
    , forall a. Output a -> [Text]
errTraceback :: [Text]
    }
  deriving (Int -> Output a -> ShowS
forall a. Int -> Output a -> ShowS
forall a. [Output a] -> ShowS
forall a. Output a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Output a] -> ShowS
$cshowList :: forall a. [Output a] -> ShowS
show :: Output a -> String
$cshow :: forall a. Output a -> String
showsPrec :: Int -> Output a -> ShowS
$cshowsPrec :: forall a. Int -> Output a -> ShowS
Show, Output a -> Output a -> Bool
forall a. Output a -> Output a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Output a -> Output a -> Bool
$c/= :: forall a. Output a -> Output a -> Bool
== :: Output a -> Output a -> Bool
$c== :: forall a. Output a -> Output a -> Bool
Eq, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Output a) x -> Output a
forall a x. Output a -> Rep (Output a) x
$cto :: forall a x. Rep (Output a) x -> Output a
$cfrom :: forall a x. Output a -> Rep (Output a) x
Generic)

instance FromJSON (Output NbV4) where
  parseJSON :: Value -> Parser (Output NbV4)
parseJSON = forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"Object" forall a b. (a -> b) -> a -> b
$ \Object
v -> do
    String
ty <- Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"output_type"
    case String
ty of
      String
"stream" ->
        forall a. Text -> Source -> Output a
Stream
          forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"name"
          forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"text"
      String
"display_data" ->
        forall a. MimeBundle -> JSONMeta -> Output a
DisplayData
          forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"data"
          forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"metadata" forall a. Parser (Maybe a) -> a -> Parser a
.!= forall a. Monoid a => a
mempty
      String
"execute_result" ->
        forall a. Int -> MimeBundle -> JSONMeta -> Output a
ExecuteResult
          forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"execution_count"
          forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"data"
          forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"metadata" forall a. Parser (Maybe a) -> a -> Parser a
.!= forall a. Monoid a => a
mempty
      String
"error" ->
        forall a. Text -> Text -> [Text] -> Output a
Err
          forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"ename"
          forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"evalue"
          forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"traceback"
      String
_ -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"Unknown object_type " forall a. [a] -> [a] -> [a]
++ String
ty

instance FromJSON (Output NbV3) where
  parseJSON :: Value -> Parser (Output NbV3)
parseJSON = forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"Object" forall a b. (a -> b) -> a -> b
$ \Object
v -> do
    String
ty <- Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"output_type"
    case String
ty of
      String
"stream" ->
        forall a. Text -> Source -> Output a
Stream
          forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"stream"
          forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"text"
      String
"display_data" ->
        forall a. MimeBundle -> JSONMeta -> Output a
DisplayData
          forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object -> Parser MimeBundle
extractNbV3Data Object
v
          forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"metadata" forall a. Parser (Maybe a) -> a -> Parser a
.!= forall a. Monoid a => a
mempty
      String
"pyout" ->
        forall a. Int -> MimeBundle -> JSONMeta -> Output a
ExecuteResult
          forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"prompt_number"
          forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object -> Parser MimeBundle
extractNbV3Data Object
v
          forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"metadata" forall a. Parser (Maybe a) -> a -> Parser a
.!= forall a. Monoid a => a
mempty
      String
"pyerr" ->
        forall a. Text -> Text -> [Text] -> Output a
Err
          forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"ename"
          forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"evalue"
          forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"traceback"
      String
_ -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"Unknown object_type " forall a. [a] -> [a] -> [a]
++ String
ty

-- Remove keys output_type, prompt_number, metadata;
-- change short keys like text and png to mime types.
extractNbV3Data :: Aeson.Object -> Aeson.Parser MimeBundle
extractNbV3Data :: Object -> Parser MimeBundle
extractNbV3Data Object
v = do
  let go :: (a, b) -> Maybe (a, b)
go (a
"output_type", b
_)   = forall a. Maybe a
Nothing
      go (a
"metadata", b
_)      = forall a. Maybe a
Nothing
      go (a
"prompt_number", b
_) = forall a. Maybe a
Nothing
      go (a
"text", b
x)          = forall a. a -> Maybe a
Just (a
"text/plain", b
x)
      go (a
"latex", b
x)         = forall a. a -> Maybe a
Just (a
"text/latex", b
x)
      go (a
"html", b
x)          = forall a. a -> Maybe a
Just (a
"text/html", b
x)
      go (a
"png", b
x)           = forall a. a -> Maybe a
Just (a
"image/png", b
x)
      go (a
"jpeg", b
x)          = forall a. a -> Maybe a
Just (a
"image/jpeg", b
x)
      go (a
"javascript", b
x)    = forall a. a -> Maybe a
Just (a
"application/javascript", b
x)
      go (a
_, b
_)               = forall a. Maybe a
Nothing -- TODO complete list? where documented?
  forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall v. [(Key, v)] -> KeyMap v
KM.fromList forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe forall {a} {a} {b}.
(Eq a, IsString a, IsString a) =>
(a, b) -> Maybe (a, b)
go forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall v. KeyMap v -> [(Key, v)]
KM.toList forall a b. (a -> b) -> a -> b
$ Object
v)

instance ToJSON (Output NbV4) where
  toJSON :: Output NbV4 -> Value
toJSON s :: Output NbV4
s@Stream{} = [Pair] -> Value
object
    [ Key
"output_type" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= (Text
"stream" :: Text)
    , Key
"name" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Output a -> Text
streamName Output NbV4
s
    , Key
"text" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Output a -> Source
streamText Output NbV4
s
    ]
  toJSON d :: Output NbV4
d@DisplayData{} = [Pair] -> Value
object
    [ Key
"output_type" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= (Text
"display_data" :: Text)
    , Key
"data" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Output a -> MimeBundle
displayData Output NbV4
d
    , Key
"metadata" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Output a -> JSONMeta
displayMetadata Output NbV4
d
    ]
  toJSON e :: Output NbV4
e@ExecuteResult{} = [Pair] -> Value
object
    [ Key
"output_type" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= (Text
"execute_result" :: Text)
    , Key
"execution_count" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Output a -> Int
executeCount Output NbV4
e
    , Key
"data" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Output a -> MimeBundle
executeData Output NbV4
e
    , Key
"metadata" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Output a -> JSONMeta
executeMetadata Output NbV4
e
    ]
  toJSON e :: Output NbV4
e@Err{} = [Pair] -> Value
object
    [ Key
"output_type" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= (Text
"error" :: Text)
    , Key
"ename" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Output a -> Text
errName Output NbV4
e
    , Key
"evalue" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Output a -> Text
errValue Output NbV4
e
    , Key
"traceback" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Output a -> [Text]
errTraceback Output NbV4
e
    ]

instance ToJSON (Output NbV3) where
  toJSON :: Output NbV3 -> Value
toJSON s :: Output NbV3
s@Stream{} = [Pair] -> Value
object
    [ Key
"output_type" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= (Text
"stream" :: Text)
    , Key
"stream" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Output a -> Text
streamName Output NbV3
s
    , Key
"text" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Output a -> Source
streamText Output NbV3
s
    ]
  toJSON d :: Output NbV3
d@DisplayData{} =
    Value -> Value
adjustV3DataFields forall a b. (a -> b) -> a -> b
$ [Pair] -> Value
object
    [ Key
"output_type" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= (Text
"display_data" :: Text)
    , Key
"data" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Output a -> MimeBundle
displayData Output NbV3
d
    , Key
"metadata" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Output a -> JSONMeta
displayMetadata Output NbV3
d ]
  toJSON e :: Output NbV3
e@ExecuteResult{} =
    Value -> Value
adjustV3DataFields forall a b. (a -> b) -> a -> b
$ [Pair] -> Value
object
    [ Key
"output_type" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= (Text
"pyout" :: Text)
    , Key
"prompt_number" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Output a -> Int
executeCount Output NbV3
e
    , Key
"data" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Output a -> MimeBundle
executeData Output NbV3
e
    , Key
"metadata" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Output a -> JSONMeta
executeMetadata Output NbV3
e ]
  toJSON e :: Output NbV3
e@Err{} = [Pair] -> Value
object
    [ Key
"output_type" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= (Text
"pyerr" :: Text)
    , Key
"ename" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Output a -> Text
errName Output NbV3
e
    , Key
"evalue" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Output a -> Text
errValue Output NbV3
e
    , Key
"traceback" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. Output a -> [Text]
errTraceback Output NbV3
e
    ]

adjustV3DataFields :: Value -> Value
adjustV3DataFields :: Value -> Value
adjustV3DataFields (Object Object
hm) =
  case forall v. Key -> KeyMap v -> Maybe v
KM.lookup Key
"data" Object
hm of
    Just (Object Object
dm) -> Object -> Value
Object forall a b. (a -> b) -> a -> b
$
      forall v. Key -> KeyMap v -> KeyMap v
KM.delete Key
"data" forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr
      (\(Key
k, Value
v) -> forall v. Key -> v -> KeyMap v -> KeyMap v
KM.insert (forall {a}. (Eq a, IsString a) => a -> a
modKey Key
k) Value
v) Object
hm
      (forall v. KeyMap v -> [(Key, v)]
KM.toList Object
dm)
    Maybe Value
_ -> Object -> Value
Object Object
hm
  where  modKey :: a -> a
modKey a
"text/plain"             = a
"text"
         modKey a
"text/latex"             = a
"latex"
         modKey a
"text/html"              = a
"html"
         modKey a
"image/jpeg"             = a
"jpeg"
         modKey a
"image/png"              = a
"png"
         modKey a
"application/javascript" = a
"javascript"
         modKey a
x                        = a
x
adjustV3DataFields Value
x = Value
x

-- | Data in an execution result or display data cell.
data MimeData =
    BinaryData ByteString
  | TextualData Text
  | JsonData Value
  deriving (Int -> MimeData -> ShowS
[MimeData] -> ShowS
MimeData -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MimeData] -> ShowS
$cshowList :: [MimeData] -> ShowS
show :: MimeData -> String
$cshow :: MimeData -> String
showsPrec :: Int -> MimeData -> ShowS
$cshowsPrec :: Int -> MimeData -> ShowS
Show, MimeData -> MimeData -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MimeData -> MimeData -> Bool
$c/= :: MimeData -> MimeData -> Bool
== :: MimeData -> MimeData -> Bool
$c== :: MimeData -> MimeData -> Bool
Eq, Eq MimeData
MimeData -> MimeData -> Bool
MimeData -> MimeData -> Ordering
MimeData -> MimeData -> MimeData
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: MimeData -> MimeData -> MimeData
$cmin :: MimeData -> MimeData -> MimeData
max :: MimeData -> MimeData -> MimeData
$cmax :: MimeData -> MimeData -> MimeData
>= :: MimeData -> MimeData -> Bool
$c>= :: MimeData -> MimeData -> Bool
> :: MimeData -> MimeData -> Bool
$c> :: MimeData -> MimeData -> Bool
<= :: MimeData -> MimeData -> Bool
$c<= :: MimeData -> MimeData -> Bool
< :: MimeData -> MimeData -> Bool
$c< :: MimeData -> MimeData -> Bool
compare :: MimeData -> MimeData -> Ordering
$ccompare :: MimeData -> MimeData -> Ordering
Ord, forall x. Rep MimeData x -> MimeData
forall x. MimeData -> Rep MimeData x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep MimeData x -> MimeData
$cfrom :: forall x. MimeData -> Rep MimeData x
Generic)

instance ToJSON MimeData where
  toJSON :: MimeData -> Value
toJSON = forall a. ToJSON a => a -> Value
toJSON forall b c a. (b -> c) -> (a -> b) -> a -> c
. MimeData -> Value
mimeDataToValue
  toEncoding :: MimeData -> Encoding
toEncoding = forall a. ToJSON a => a -> Encoding
toEncoding forall b c a. (b -> c) -> (a -> b) -> a -> c
. MimeData -> Value
mimeDataToValue

mimeDataToValue :: MimeData -> Value
mimeDataToValue :: MimeData -> Value
mimeDataToValue (BinaryData ByteString
bs) =
  forall a. ToJSON a => a -> Value
toJSON forall b c a. (b -> c) -> (a -> b) -> a -> c
.
    ByteString -> Text
TE.decodeUtf8 forall b c a. (b -> c) -> (a -> b) -> a -> c
.
    (forall a. Semigroup a => a -> a -> a
<> ByteString
"\n") forall b c a. (b -> c) -> (a -> b) -> a -> c
.
    ByteString -> [ByteString] -> ByteString
B.intercalate ByteString
"\n" forall b c a. (b -> c) -> (a -> b) -> a -> c
.  Int -> ByteString -> [ByteString]
chunksOf Int
76 forall b c a. (b -> c) -> (a -> b) -> a -> c
.
    ByteString -> ByteString
Base64.encode
    forall a b. (a -> b) -> a -> b
$ ByteString
bs
mimeDataToValue (JsonData Value
v) = Value
v
mimeDataToValue (TextualData Text
t) = forall a. ToJSON a => a -> Value
toJSON (Text -> [Text]
breakLines Text
t)

type MimeType = Text

-- | A 'MimeBundle' wraps a map from mime types to mime data.
newtype MimeBundle = MimeBundle{ MimeBundle -> Map Text MimeData
unMimeBundle :: M.Map MimeType MimeData }
  deriving (Int -> MimeBundle -> ShowS
[MimeBundle] -> ShowS
MimeBundle -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MimeBundle] -> ShowS
$cshowList :: [MimeBundle] -> ShowS
show :: MimeBundle -> String
$cshow :: MimeBundle -> String
showsPrec :: Int -> MimeBundle -> ShowS
$cshowsPrec :: Int -> MimeBundle -> ShowS
Show, MimeBundle -> MimeBundle -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MimeBundle -> MimeBundle -> Bool
$c/= :: MimeBundle -> MimeBundle -> Bool
== :: MimeBundle -> MimeBundle -> Bool
$c== :: MimeBundle -> MimeBundle -> Bool
Eq, Eq MimeBundle
MimeBundle -> MimeBundle -> Bool
MimeBundle -> MimeBundle -> Ordering
MimeBundle -> MimeBundle -> MimeBundle
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: MimeBundle -> MimeBundle -> MimeBundle
$cmin :: MimeBundle -> MimeBundle -> MimeBundle
max :: MimeBundle -> MimeBundle -> MimeBundle
$cmax :: MimeBundle -> MimeBundle -> MimeBundle
>= :: MimeBundle -> MimeBundle -> Bool
$c>= :: MimeBundle -> MimeBundle -> Bool
> :: MimeBundle -> MimeBundle -> Bool
$c> :: MimeBundle -> MimeBundle -> Bool
<= :: MimeBundle -> MimeBundle -> Bool
$c<= :: MimeBundle -> MimeBundle -> Bool
< :: MimeBundle -> MimeBundle -> Bool
$c< :: MimeBundle -> MimeBundle -> Bool
compare :: MimeBundle -> MimeBundle -> Ordering
$ccompare :: MimeBundle -> MimeBundle -> Ordering
Ord, forall x. Rep MimeBundle x -> MimeBundle
forall x. MimeBundle -> Rep MimeBundle x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep MimeBundle x -> MimeBundle
$cfrom :: forall x. MimeBundle -> Rep MimeBundle x
Generic, NonEmpty MimeBundle -> MimeBundle
MimeBundle -> MimeBundle -> MimeBundle
forall b. Integral b => b -> MimeBundle -> MimeBundle
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: forall b. Integral b => b -> MimeBundle -> MimeBundle
$cstimes :: forall b. Integral b => b -> MimeBundle -> MimeBundle
sconcat :: NonEmpty MimeBundle -> MimeBundle
$csconcat :: NonEmpty MimeBundle -> MimeBundle
<> :: MimeBundle -> MimeBundle -> MimeBundle
$c<> :: MimeBundle -> MimeBundle -> MimeBundle
Semigroup, Semigroup MimeBundle
MimeBundle
[MimeBundle] -> MimeBundle
MimeBundle -> MimeBundle -> MimeBundle
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [MimeBundle] -> MimeBundle
$cmconcat :: [MimeBundle] -> MimeBundle
mappend :: MimeBundle -> MimeBundle -> MimeBundle
$cmappend :: MimeBundle -> MimeBundle -> MimeBundle
mempty :: MimeBundle
$cmempty :: MimeBundle
Monoid)

instance FromJSON MimeBundle where
  parseJSON :: Value -> Parser MimeBundle
parseJSON Value
v = do
    [(Text, MimeData)]
m <- forall a. FromJSON a => Value -> Parser a
parseJSON Value
v forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (Text, Value) -> Parser (Text, MimeData)
pairToMimeData forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall k a. Map k a -> [(k, a)]
M.toList
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Map Text MimeData -> MimeBundle
MimeBundle forall a b. (a -> b) -> a -> b
$ forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [(Text, MimeData)]
m

pairToMimeData :: (MimeType, Value) -> Aeson.Parser (MimeType, MimeData)
pairToMimeData :: (Text, Value) -> Parser (Text, MimeData)
pairToMimeData (Text
mt, Value
v)
  | Text
mt forall a. Eq a => a -> a -> Bool
== Text
"application/json" Bool -> Bool -> Bool
||
    Text
"+json" Text -> Text -> Bool
`T.isSuffixOf` Text
mt = forall (m :: * -> *) a. Monad m => a -> m a
return (Text
mt, Value -> MimeData
JsonData Value
v)
pairToMimeData (Text
mt, Value
v) = do
  Text
t <- forall a. FromJSON a => Value -> Parser a
parseJSON Value
v forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (forall a. Monoid a => [a] -> a
mconcat forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromJSON a => Value -> Parser a
parseJSON Value
v)
  let mimeprefix :: Text
mimeprefix = (Char -> Bool) -> Text -> Text
T.takeWhile (forall a. Eq a => a -> a -> Bool
/=Char
'/') Text
mt
  if Text
mimeprefix forall a. Eq a => a -> a -> Bool
== Text
"text"
     then forall (m :: * -> *) a. Monad m => a -> m a
return (Text
mt, Text -> MimeData
TextualData Text
t)
     else
       case ByteString -> Either String ByteString
Base64.decode (Text -> ByteString
TE.encodeUtf8 ((Char -> Bool) -> Text -> Text
T.filter (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isSpace) Text
t)) of
            Left String
_  -> forall (m :: * -> *) a. Monad m => a -> m a
return (Text
mt, Text -> MimeData
TextualData Text
t)
            Right ByteString
b -> forall (m :: * -> *) a. Monad m => a -> m a
return (Text
mt, ByteString -> MimeData
BinaryData ByteString
b)

instance ToJSON MimeBundle where
  toJSON :: MimeBundle -> Value
toJSON (MimeBundle Map Text MimeData
m) =
    forall a. ToJSON a => a -> Value
toJSON Map Text MimeData
m
  toEncoding :: MimeBundle -> Encoding
toEncoding (MimeBundle Map Text MimeData
m) =  -- ensure deterministic (sorted) order
    Series -> Encoding
pairs forall a b. (a -> b) -> a -> b
$ forall a. Monoid a => [a] -> a
mconcat forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (\(Text
k,MimeData
v) -> (forall a. IsString a => String -> a
fromString (Text -> String
T.unpack Text
k) forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
Aeson..= MimeData
v))
                          (forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn forall a b. (a, b) -> a
fst (forall k a. Map k a -> [(k, a)]
M.toList Map Text MimeData
m))

chunksOf :: Int -> ByteString -> [ByteString]
chunksOf :: Int -> ByteString -> [ByteString]
chunksOf Int
k ByteString
s
   | ByteString -> Bool
B.null ByteString
s = []
   | Bool
otherwise =
     let (ByteString
h,ByteString
t) = Int -> ByteString -> (ByteString, ByteString)
B.splitAt Int
k ByteString
s
     in ByteString
h forall a. a -> [a] -> [a]
: Int -> ByteString -> [ByteString]
chunksOf Int
k ByteString
t

-- | Break up a string into a list of strings, each representing
-- one line of the string (including trailing newline if any).
breakLines :: Text -> [Text]
breakLines :: Text -> [Text]
breakLines Text
t =
  let (Text
x, Text
y) = (Char -> Bool) -> Text -> (Text, Text)
T.break (forall a. Eq a => a -> a -> Bool
==Char
'\n') Text
t
  in  case Text -> Maybe (Char, Text)
T.uncons Text
y of
         Maybe (Char, Text)
Nothing        -> if Text -> Bool
T.null Text
x then [] else [Text
x]
         Just (Char
c, Text
rest) -> (Text
x forall a. Semigroup a => a -> a -> a
<> Char -> Text
T.singleton Char
c) forall a. a -> [a] -> [a]
: Text -> [Text]
breakLines Text
rest