module Emanote.Pandoc.Markdown.Parser
  ( parseMarkdown,
  )
where

import Commonmark qualified as CM
import Commonmark.Extensions qualified as CE
import Commonmark.Extensions.WikiLink qualified as WL
import Commonmark.Simple (parseMarkdownWithFrontMatter)
import Data.Aeson qualified as Aeson
import Emanote.Pandoc.Markdown.Syntax.HashTag qualified as IT
import Emanote.Pandoc.Markdown.Syntax.Highlight qualified as IH
import Relude
import Text.Pandoc.Definition (Pandoc)

parseMarkdown :: FilePath -> Text -> Either Text (Maybe Aeson.Value, Pandoc)
parseMarkdown :: FilePath -> Text -> Either Text (Maybe Value, Pandoc)
parseMarkdown =
  forall meta (m :: Type -> Type) il bl.
(FromJSON meta,
 (m :: (Type -> Type)) ~ (Either ParseError :: (Type -> Type)),
 (bl :: Type) ~ (Cm () Blocks :: Type),
 (il :: Type) ~ (Cm () Inlines :: Type)) =>
SyntaxSpec m il bl
-> FilePath -> Text -> Either Text (Maybe meta, Pandoc)
parseMarkdownWithFrontMatter @Aeson.Value (SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
 -> FilePath -> Text -> Either Text (Maybe Value, Pandoc))
-> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
-> FilePath
-> Text
-> Either Text (Maybe Value, Pandoc)
forall a b. (a -> b) -> a -> b
$
    -- As the commonmark documentation states, pipeTableSpec should be placed after
    -- fancyListSpec and defaultSyntaxSpec to avoid bad results when parsing
    -- non-table lines.
    -- see https://github.com/jgm/commonmark-hs/issues/52
    SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
baseExtsSansPipeTable
      SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
-> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
-> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall a. Semigroup a => a -> a -> a
<> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
gfmExtensionsSansPipeTable
      SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
-> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
-> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall a. Semigroup a => a -> a -> a
<> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il, HasPipeTable il bl) =>
SyntaxSpec m il bl
CE.pipeTableSpec
      SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
-> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
-> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall a. Semigroup a => a -> a -> a
<> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall (m :: Type -> Type) il bl.
(Monad m, IsInline il, HasWikiLink il) =>
SyntaxSpec m il bl
WL.wikilinkSpec
      -- ASK: Can we conditionally disable this?
      -- cf. https://github.com/srid/emanote/issues/167
      SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
-> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
-> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall a. Semigroup a => a -> a -> a
<> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il, HasHashTag il) =>
SyntaxSpec m il bl
IT.hashTagSpec
      SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
-> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
-> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall a. Semigroup a => a -> a -> a
<> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall (m :: Type -> Type) il bl.
(Monad m, IsInline il, HasHighlight il) =>
SyntaxSpec m il bl
IH.highlightSpec
  where
    baseExtsSansPipeTable :: SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
baseExtsSansPipeTable =
      [SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)]
-> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall a. Monoid a => [a] -> a
mconcat
        [ SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il) =>
SyntaxSpec m il bl
CE.fancyListSpec,
          SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall (m :: Type -> Type) il bl.
(Monad m, Typeable @(Type -> Type) m, IsBlock il bl, IsInline il,
 Typeable @Type il, Typeable @Type bl, HasFootnote il bl) =>
SyntaxSpec m il bl
CE.footnoteSpec,
          SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il, HasMath il) =>
SyntaxSpec m il bl
CE.mathSpec,
          SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il, HasQuoted il) =>
SyntaxSpec m il bl
CE.smartPunctuationSpec,
          SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il, Typeable @Type il,
 Typeable @Type bl, HasDefinitionList il bl) =>
SyntaxSpec m il bl
CE.definitionListSpec,
          SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall (m :: Type -> Type) il bl.
(Monad m, IsInline il) =>
SyntaxSpec m il bl
CE.attributesSpec,
          SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl) =>
SyntaxSpec m il bl
CE.rawAttributeSpec,
          SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall (m :: Type -> Type) il bl.
(Monad m, IsInline il, IsBlock il bl, HasDiv bl) =>
SyntaxSpec m il bl
CE.fencedDivSpec,
          SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall (m :: Type -> Type) il bl.
(Monad m, IsInline il, HasSpan il) =>
SyntaxSpec m il bl
CE.bracketedSpanSpec,
          SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il) =>
SyntaxSpec m il bl
CE.autolinkSpec,
          SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il) =>
SyntaxSpec m il bl
CM.defaultSyntaxSpec
        ]
    gfmExtensionsSansPipeTable :: SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
gfmExtensionsSansPipeTable =
      SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il, HasEmoji il) =>
SyntaxSpec m il bl
CE.emojiSpec
        SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
-> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
-> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall a. Semigroup a => a -> a -> a
<> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il, HasStrikethrough il) =>
SyntaxSpec m il bl
CE.strikethroughSpec
        SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
-> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
-> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall a. Semigroup a => a -> a -> a
<> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il) =>
SyntaxSpec m il bl
CE.autolinkSpec
        SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
-> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
-> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall a. Semigroup a => a -> a -> a
<> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il, ToPlainText il) =>
SyntaxSpec m il bl
CE.autoIdentifiersSpec
        SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
-> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
-> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall a. Semigroup a => a -> a -> a
<> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il, HasTaskList il bl) =>
SyntaxSpec m il bl
CE.taskListSpec