module Nbparts.Pack.Sources.Markdown where
import Control.Applicative (Alternative ((<|>)))
import Control.Arrow (left)
import Control.Monad qualified as Monad
import Data.Aeson qualified as Aeson
import Data.Map qualified as Map
import Data.Maybe qualified as Maybe
import Data.Text (Text)
import Data.Text qualified as Text
import Data.Text.Encoding qualified as Text
import Nbparts.Types
( CellMarker (CellMarker),
CellSource (CellSource),
CellType (Code, Markdown, Raw),
PackError (PackParseMarkdownSourcesError),
ParseMarkdownSourcesError (ParseMarkdownSourcesJsonError, ParseMarkdownSourcesMarkdownError),
UnembeddedMimeAttachments (UnembeddedMimeAttachments),
UnembeddedMimeBundle (UnembeddedMimeBundle),
UnembeddedMimeData (BinaryData),
)
import Nbparts.Util.Markdown qualified as MarkdownUtil
import Nbparts.Util.Text qualified as TextUtil
import Text.Megaparsec (Parsec)
import Text.Megaparsec qualified as P
import Text.Megaparsec.Char qualified as P
type Parser = Parsec ParseMarkdownSourcesError Text
markdownToSources :: String -> Text -> Either PackError [CellSource]
markdownToSources :: FilePath -> Text -> Either PackError [CellSource]
markdownToSources FilePath
filename Text
mdText = (ParseErrorBundle Text ParseMarkdownSourcesError -> PackError)
-> Either
(ParseErrorBundle Text ParseMarkdownSourcesError) [CellSource]
-> Either PackError [CellSource]
forall b c d. (b -> c) -> Either b d -> Either c d
forall (a :: * -> * -> *) b c d.
ArrowChoice a =>
a b c -> a (Either b d) (Either c d)
left ParseErrorBundle Text ParseMarkdownSourcesError -> PackError
PackParseMarkdownSourcesError (Either
(ParseErrorBundle Text ParseMarkdownSourcesError) [CellSource]
-> Either PackError [CellSource])
-> Either
(ParseErrorBundle Text ParseMarkdownSourcesError) [CellSource]
-> Either PackError [CellSource]
forall a b. (a -> b) -> a -> b
$ Parsec ParseMarkdownSourcesError Text [CellSource]
-> FilePath
-> Text
-> Either
(ParseErrorBundle Text ParseMarkdownSourcesError) [CellSource]
forall e s a.
Parsec e s a -> FilePath -> s -> Either (ParseErrorBundle s e) a
P.runParser Parsec ParseMarkdownSourcesError Text [CellSource]
parseSources FilePath
filename Text
mdText
parseSources :: Parser [CellSource]
parseSources :: Parsec ParseMarkdownSourcesError Text [CellSource]
parseSources = ParsecT ParseMarkdownSourcesError Text Identity CellSource
-> Parsec ParseMarkdownSourcesError Text [CellSource]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
P.many ParsecT ParseMarkdownSourcesError Text Identity CellSource
parseSource
parseSource :: Parser CellSource
parseSource :: ParsecT ParseMarkdownSourcesError Text Identity CellSource
parseSource = do
(CellMarker Text
cellId CellType
cellType Maybe UnembeddedMimeAttachments
maybeAttachments) <- Parser CellMarker
parseCellInfo
ParsecT ParseMarkdownSourcesError Text Identity (Maybe Char)
-> ParsecT ParseMarkdownSourcesError Text Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
Monad.void (ParsecT ParseMarkdownSourcesError Text Identity (Maybe Char)
-> ParsecT ParseMarkdownSourcesError Text Identity ())
-> ParsecT ParseMarkdownSourcesError Text Identity (Maybe Char)
-> ParsecT ParseMarkdownSourcesError Text Identity ()
forall a b. (a -> b) -> a -> b
$ ParsecT ParseMarkdownSourcesError Text Identity Char
-> ParsecT ParseMarkdownSourcesError Text Identity (Maybe Char)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
P.optional ParsecT ParseMarkdownSourcesError Text Identity Char
ParsecT ParseMarkdownSourcesError Text Identity (Token Text)
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m (Token s)
P.newline
Text
srcText <- case CellType
cellType of
CellType
Code -> ParsecT ParseMarkdownSourcesError Text Identity Text
parseCodeOrRawCell
CellType
Raw -> ParsecT ParseMarkdownSourcesError Text Identity Text
parseCodeOrRawCell
CellType
Markdown -> do
Text
mdText <- ParsecT ParseMarkdownSourcesError Text Identity Text
parseOtherCell
Blocks
mdAst <- case Text -> Either ParseError Blocks
MarkdownUtil.parseMarkdown Text
mdText of
Right Blocks
ast -> Blocks -> ParsecT ParseMarkdownSourcesError Text Identity Blocks
forall a. a -> ParsecT ParseMarkdownSourcesError Text Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Blocks
ast
Left ParseError
mdErr -> ParseMarkdownSourcesError
-> ParsecT ParseMarkdownSourcesError Text Identity Blocks
forall e s (m :: * -> *) a. MonadParsec e s m => e -> m a
P.customFailure (ParseError -> ParseMarkdownSourcesError
ParseMarkdownSourcesMarkdownError ParseError
mdErr)
let mdLines :: [Text]
mdLines = Text -> [Text]
Text.lines Text
mdText
let escapesReplacements :: [((Int, Int), Text)]
escapesReplacements = (Text -> Text) -> [Text] -> Blocks -> [((Int, Int), Text)]
MarkdownUtil.commentChangesWith Text -> Text
unescapeComments [Text]
mdLines Blocks
mdAst
let attachmentReplacements :: [((Int, Int), Text)]
attachmentReplacements = case Maybe UnembeddedMimeAttachments
maybeAttachments of
Just UnembeddedMimeAttachments
attachments ->
(Text -> Maybe Text) -> [Text] -> Blocks -> [((Int, Int), Text)]
MarkdownUtil.attachmentChangesWith
((Text -> Text) -> Maybe Text -> Maybe Text
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Text -> Text -> Text
forall a. Monoid a => a -> a -> a
mappend Text
"attachment:") (Maybe Text -> Maybe Text)
-> (Text -> Maybe Text) -> Text -> Maybe Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnembeddedMimeAttachments -> FilePath -> Maybe Text
findAttachmentNameByFilePath UnembeddedMimeAttachments
attachments (FilePath -> Maybe Text)
-> (Text -> FilePath) -> Text -> Maybe Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> FilePath
Text.unpack)
[Text]
mdLines
Blocks
mdAst
Maybe UnembeddedMimeAttachments
Nothing -> []
let textReplacements :: [((Int, Int), Text)]
textReplacements = [((Int, Int), Text)]
escapesReplacements [((Int, Int), Text)]
-> [((Int, Int), Text)] -> [((Int, Int), Text)]
forall a. Semigroup a => a -> a -> a
<> [((Int, Int), Text)]
attachmentReplacements
Text -> ParsecT ParseMarkdownSourcesError Text Identity Text
forall a. a -> ParsecT ParseMarkdownSourcesError Text Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> ParsecT ParseMarkdownSourcesError Text Identity Text)
-> (Maybe Text -> Text)
-> Maybe Text
-> ParsecT ParseMarkdownSourcesError Text Identity Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe Text -> Text
forall a. HasCallStack => Maybe a -> a
Maybe.fromJust (Maybe Text
-> ParsecT ParseMarkdownSourcesError Text Identity Text)
-> Maybe Text
-> ParsecT ParseMarkdownSourcesError Text Identity Text
forall a b. (a -> b) -> a -> b
$ Text -> [((Int, Int), Text)] -> Maybe Text
TextUtil.replaceSlices Text
mdText [((Int, Int), Text)]
textReplacements
let src :: [Text]
src = Text -> [Text]
TextUtil.splitKeepNewlines Text
srcText
CellSource
-> ParsecT ParseMarkdownSourcesError Text Identity CellSource
forall a. a -> ParsecT ParseMarkdownSourcesError Text Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CellSource
-> ParsecT ParseMarkdownSourcesError Text Identity CellSource)
-> CellSource
-> ParsecT ParseMarkdownSourcesError Text Identity CellSource
forall a b. (a -> b) -> a -> b
$ Text
-> CellType
-> [Text]
-> Maybe UnembeddedMimeAttachments
-> CellSource
CellSource Text
cellId CellType
cellType [Text]
src Maybe UnembeddedMimeAttachments
maybeAttachments
parseCodeOrRawCell :: Parser Text
parseCodeOrRawCell :: ParsecT ParseMarkdownSourcesError Text Identity Text
parseCodeOrRawCell = do
Text
code <- ParsecT ParseMarkdownSourcesError Text Identity Text
parseCodeBlock
ParsecT ParseMarkdownSourcesError Text Identity (Maybe Char)
-> ParsecT ParseMarkdownSourcesError Text Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
Monad.void (ParsecT ParseMarkdownSourcesError Text Identity (Maybe Char)
-> ParsecT ParseMarkdownSourcesError Text Identity ())
-> ParsecT ParseMarkdownSourcesError Text Identity (Maybe Char)
-> ParsecT ParseMarkdownSourcesError Text Identity ()
forall a b. (a -> b) -> a -> b
$ ParsecT ParseMarkdownSourcesError Text Identity Char
-> ParsecT ParseMarkdownSourcesError Text Identity (Maybe Char)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
P.optional (ParsecT ParseMarkdownSourcesError Text Identity Char
ParsecT ParseMarkdownSourcesError Text Identity (Token Text)
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m (Token s)
P.newline ParsecT ParseMarkdownSourcesError Text Identity Char
-> ParsecT ParseMarkdownSourcesError Text Identity Char
-> ParsecT ParseMarkdownSourcesError Text Identity Char
forall a b.
ParsecT ParseMarkdownSourcesError Text Identity a
-> ParsecT ParseMarkdownSourcesError Text Identity b
-> ParsecT ParseMarkdownSourcesError Text Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ParsecT ParseMarkdownSourcesError Text Identity Char
ParsecT ParseMarkdownSourcesError Text Identity (Token Text)
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m (Token s)
P.newline)
Text -> ParsecT ParseMarkdownSourcesError Text Identity Text
forall a. a -> ParsecT ParseMarkdownSourcesError Text Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
code
parseCodeBlock :: Parser Text
parseCodeBlock :: ParsecT ParseMarkdownSourcesError Text Identity Text
parseCodeBlock = do
ParsecT ParseMarkdownSourcesError Text Identity (Tokens Text)
-> ParsecT ParseMarkdownSourcesError Text Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
Monad.void (ParsecT ParseMarkdownSourcesError Text Identity (Tokens Text)
-> ParsecT ParseMarkdownSourcesError Text Identity ())
-> ParsecT ParseMarkdownSourcesError Text Identity (Tokens Text)
-> ParsecT ParseMarkdownSourcesError Text Identity ()
forall a b. (a -> b) -> a -> b
$ Tokens Text
-> ParsecT ParseMarkdownSourcesError Text Identity (Tokens Text)
forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
P.string Tokens Text
"```"
ParsecT ParseMarkdownSourcesError Text Identity [Token Text]
-> ParsecT ParseMarkdownSourcesError Text Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
Monad.void (ParsecT ParseMarkdownSourcesError Text Identity [Token Text]
-> ParsecT ParseMarkdownSourcesError Text Identity ())
-> ParsecT ParseMarkdownSourcesError Text Identity [Token Text]
-> ParsecT ParseMarkdownSourcesError Text Identity ()
forall a b. (a -> b) -> a -> b
$ ParsecT ParseMarkdownSourcesError Text Identity (Token Text)
-> ParsecT ParseMarkdownSourcesError Text Identity Char
-> ParsecT ParseMarkdownSourcesError Text Identity [Token Text]
forall (m :: * -> *) a end. MonadPlus m => m a -> m end -> m [a]
P.manyTill ParsecT ParseMarkdownSourcesError Text Identity (Token Text)
forall e s (m :: * -> *). MonadParsec e s m => m (Token s)
P.anySingle ParsecT ParseMarkdownSourcesError Text Identity Char
ParsecT ParseMarkdownSourcesError Text Identity (Token Text)
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m (Token s)
P.newline
Text
code <- FilePath -> Text
Text.pack (FilePath -> Text)
-> ParsecT ParseMarkdownSourcesError Text Identity FilePath
-> ParsecT ParseMarkdownSourcesError Text Identity Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT ParseMarkdownSourcesError Text Identity Char
-> ParsecT ParseMarkdownSourcesError Text Identity (Tokens Text)
-> ParsecT ParseMarkdownSourcesError Text Identity FilePath
forall (m :: * -> *) a end. MonadPlus m => m a -> m end -> m [a]
P.manyTill ParsecT ParseMarkdownSourcesError Text Identity Char
ParsecT ParseMarkdownSourcesError Text Identity (Token Text)
forall e s (m :: * -> *). MonadParsec e s m => m (Token s)
P.anySingle (Tokens Text
-> ParsecT ParseMarkdownSourcesError Text Identity (Tokens Text)
forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
P.string Tokens Text
"```")
let stripped :: Text
stripped = Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
Maybe.fromMaybe Text
code (Maybe Text -> Text) -> Maybe Text -> Text
forall a b. (a -> b) -> a -> b
$ Text -> Text -> Maybe Text
Text.stripSuffix Text
"\n" Text
code
Text -> ParsecT ParseMarkdownSourcesError Text Identity Text
forall a. a -> ParsecT ParseMarkdownSourcesError Text Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
stripped
parseOtherCell :: Parser Text
parseOtherCell :: ParsecT ParseMarkdownSourcesError Text Identity Text
parseOtherCell = do
Text
body <- FilePath -> Text
Text.pack (FilePath -> Text)
-> ParsecT ParseMarkdownSourcesError Text Identity FilePath
-> ParsecT ParseMarkdownSourcesError Text Identity Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT ParseMarkdownSourcesError Text Identity Char
-> ParsecT ParseMarkdownSourcesError Text Identity ()
-> ParsecT ParseMarkdownSourcesError Text Identity FilePath
forall (m :: * -> *) a end. MonadPlus m => m a -> m end -> m [a]
P.manyTill ParsecT ParseMarkdownSourcesError Text Identity Char
ParsecT ParseMarkdownSourcesError Text Identity (Token Text)
forall e s (m :: * -> *). MonadParsec e s m => m (Token s)
P.anySingle (ParsecT ParseMarkdownSourcesError Text Identity ()
-> ParsecT ParseMarkdownSourcesError Text Identity ()
forall a.
ParsecT ParseMarkdownSourcesError Text Identity a
-> ParsecT ParseMarkdownSourcesError Text Identity a
forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
P.lookAhead (Parser CellMarker
-> ParsecT ParseMarkdownSourcesError Text Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
Monad.void (Parser CellMarker -> Parser CellMarker
forall a.
ParsecT ParseMarkdownSourcesError Text Identity a
-> ParsecT ParseMarkdownSourcesError Text Identity a
forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
P.try Parser CellMarker
parseCellInfo) ParsecT ParseMarkdownSourcesError Text Identity ()
-> ParsecT ParseMarkdownSourcesError Text Identity ()
-> ParsecT ParseMarkdownSourcesError Text Identity ()
forall a.
ParsecT ParseMarkdownSourcesError Text Identity a
-> ParsecT ParseMarkdownSourcesError Text Identity a
-> ParsecT ParseMarkdownSourcesError Text Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> ParsecT ParseMarkdownSourcesError Text Identity ()
forall e s (m :: * -> *). MonadParsec e s m => m ()
P.eof))
Text -> ParsecT ParseMarkdownSourcesError Text Identity Text
forall a. a -> ParsecT ParseMarkdownSourcesError Text Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> ParsecT ParseMarkdownSourcesError Text Identity Text)
-> Text -> ParsecT ParseMarkdownSourcesError Text Identity Text
forall a b. (a -> b) -> a -> b
$ Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
Maybe.fromMaybe Text
body (Maybe Text -> Text) -> Maybe Text -> Text
forall a b. (a -> b) -> a -> b
$ Text -> Text -> Maybe Text
Text.stripSuffix Text
"\n\n" Text
body
parseCellInfo :: Parser CellMarker
parseCellInfo :: Parser CellMarker
parseCellInfo = do
ParsecT ParseMarkdownSourcesError Text Identity (Tokens Text)
-> ParsecT ParseMarkdownSourcesError Text Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
Monad.void (ParsecT ParseMarkdownSourcesError Text Identity (Tokens Text)
-> ParsecT ParseMarkdownSourcesError Text Identity ())
-> ParsecT ParseMarkdownSourcesError Text Identity (Tokens Text)
-> ParsecT ParseMarkdownSourcesError Text Identity ()
forall a b. (a -> b) -> a -> b
$ Tokens Text
-> ParsecT ParseMarkdownSourcesError Text Identity (Tokens Text)
forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
P.string Tokens Text
"<!--"
ParsecT ParseMarkdownSourcesError Text Identity ()
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
P.space
ParsecT ParseMarkdownSourcesError Text Identity (Tokens Text)
-> ParsecT ParseMarkdownSourcesError Text Identity ()
forall (f :: * -> *) a. Functor f => f a -> f ()
Monad.void (ParsecT ParseMarkdownSourcesError Text Identity (Tokens Text)
-> ParsecT ParseMarkdownSourcesError Text Identity ())
-> ParsecT ParseMarkdownSourcesError Text Identity (Tokens Text)
-> ParsecT ParseMarkdownSourcesError Text Identity ()
forall a b. (a -> b) -> a -> b
$ Tokens Text
-> ParsecT ParseMarkdownSourcesError Text Identity (Tokens Text)
forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
P.string Tokens Text
"nbparts:cell"
ParsecT ParseMarkdownSourcesError Text Identity ()
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
P.space1
Text
json <- FilePath -> Text
Text.pack (FilePath -> Text)
-> ParsecT ParseMarkdownSourcesError Text Identity FilePath
-> ParsecT ParseMarkdownSourcesError Text Identity Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT ParseMarkdownSourcesError Text Identity Char
-> ParsecT ParseMarkdownSourcesError Text Identity (Tokens Text)
-> ParsecT ParseMarkdownSourcesError Text Identity FilePath
forall (m :: * -> *) a end. MonadPlus m => m a -> m end -> m [a]
P.manyTill ParsecT ParseMarkdownSourcesError Text Identity Char
ParsecT ParseMarkdownSourcesError Text Identity (Token Text)
forall e s (m :: * -> *). MonadParsec e s m => m (Token s)
P.anySingle (Tokens Text
-> ParsecT ParseMarkdownSourcesError Text Identity (Tokens Text)
forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
P.string Tokens Text
"-->")
let jsonUnescaped :: Text
jsonUnescaped = Text -> Text
unescapeCellMarkerContent Text
json
case ByteString -> Either FilePath CellMarker
forall a. FromJSON a => ByteString -> Either FilePath a
Aeson.eitherDecodeStrict (Text -> ByteString
Text.encodeUtf8 Text
jsonUnescaped) of
Right CellMarker
cellInfo -> CellMarker -> Parser CellMarker
forall a. a -> ParsecT ParseMarkdownSourcesError Text Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure CellMarker
cellInfo
Left FilePath
err -> ParseMarkdownSourcesError -> Parser CellMarker
forall e s (m :: * -> *) a. MonadParsec e s m => e -> m a
P.customFailure (Text -> ParseMarkdownSourcesError
ParseMarkdownSourcesJsonError (Text -> ParseMarkdownSourcesError)
-> Text -> ParseMarkdownSourcesError
forall a b. (a -> b) -> a -> b
$ FilePath -> Text
Text.pack FilePath
err)
unescapeComments :: Text -> Text
= HasCallStack => Text -> Text -> Text -> Text
Text -> Text -> Text -> Text
Text.replace Text
"\\\\" Text
"\\" (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HasCallStack => Text -> Text -> Text -> Text
Text -> Text -> Text -> Text
Text.replace Text
"\\nbparts:cell" Text
"nbparts:cell"
findAttachmentNameByFilePath :: UnembeddedMimeAttachments -> FilePath -> Maybe Text
findAttachmentNameByFilePath :: UnembeddedMimeAttachments -> FilePath -> Maybe Text
findAttachmentNameByFilePath (UnembeddedMimeAttachments Map Text UnembeddedMimeBundle
attachments) FilePath
targetFp =
(Text -> UnembeddedMimeBundle -> Maybe Text -> Maybe Text)
-> Maybe Text -> Map Text UnembeddedMimeBundle -> Maybe Text
forall k a b. (k -> a -> b -> b) -> b -> Map k a -> b
Map.foldrWithKey Text -> UnembeddedMimeBundle -> Maybe Text -> Maybe Text
go Maybe Text
forall a. Maybe a
Nothing Map Text UnembeddedMimeBundle
attachments
where
go :: Text -> UnembeddedMimeBundle -> Maybe Text -> Maybe Text
go :: Text -> UnembeddedMimeBundle -> Maybe Text -> Maybe Text
go Text
attachmentName (UnembeddedMimeBundle Map Text UnembeddedMimeData
bundle) Maybe Text
acc =
Maybe Text
acc
Maybe Text -> Maybe Text -> Maybe Text
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> if (UnembeddedMimeData -> Bool) -> [UnembeddedMimeData] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (FilePath -> UnembeddedMimeData -> Bool
matches FilePath
targetFp) (Map Text UnembeddedMimeData -> [UnembeddedMimeData]
forall k a. Map k a -> [a]
Map.elems Map Text UnembeddedMimeData
bundle)
then Text -> Maybe Text
forall a. a -> Maybe a
Just Text
attachmentName
else Maybe Text
forall a. Maybe a
Nothing
matches :: FilePath -> UnembeddedMimeData -> Bool
matches :: FilePath -> UnembeddedMimeData -> Bool
matches FilePath
targetFp' (BinaryData FilePath
fp) = FilePath
fp FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
targetFp'
matches FilePath
_ UnembeddedMimeData
_ = Bool
False
unescapeCellMarkerContent :: Text -> Text
unescapeCellMarkerContent :: Text -> Text
unescapeCellMarkerContent = HasCallStack => Text -> Text -> Text -> Text
Text -> Text -> Text -> Text
Text.replace Text
"\\\\" Text
"\\" (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HasCallStack => Text -> Text -> Text -> Text
Text -> Text -> Text -> Text
Text.replace Text
"-\\->" Text
"-->"