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 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
      forall a. Semigroup a => a -> a -> a
<> SyntaxSpec (Either ParseError) (Cm () Inlines) (Cm () Blocks)
gfmExtensionsSansPipeTable
      forall a. Semigroup a => a -> a -> a
<> forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il, HasPipeTable il bl) =>
SyntaxSpec m il bl
CE.pipeTableSpec
      forall a. Semigroup a => a -> a -> a
<> 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
      forall a. Semigroup a => a -> a -> a
<> forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il, HasHashTag il) =>
SyntaxSpec m il bl
IT.hashTagSpec
      forall a. Semigroup a => a -> a -> a
<> 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 =
      forall a. Monoid a => [a] -> a
mconcat
        [ forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il) =>
SyntaxSpec m il bl
CE.fancyListSpec
        , 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
        , forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il, HasMath il) =>
SyntaxSpec m il bl
CE.mathSpec
        , forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il, HasQuoted il) =>
SyntaxSpec m il bl
CE.smartPunctuationSpec
        , 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
        , forall (m :: Type -> Type) il bl.
(Monad m, IsInline il) =>
SyntaxSpec m il bl
CE.attributesSpec
        , forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl) =>
SyntaxSpec m il bl
CE.rawAttributeSpec
        , forall (m :: Type -> Type) il bl.
(Monad m, IsInline il, IsBlock il bl, HasDiv bl) =>
SyntaxSpec m il bl
CE.fencedDivSpec
        , forall (m :: Type -> Type) il bl.
(Monad m, IsInline il, HasSpan il) =>
SyntaxSpec m il bl
CE.bracketedSpanSpec
        , forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il) =>
SyntaxSpec m il bl
CE.autolinkSpec
        , 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 =
      forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il, HasEmoji il) =>
SyntaxSpec m il bl
CE.emojiSpec
        forall a. Semigroup a => a -> a -> a
<> forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il, HasStrikethrough il) =>
SyntaxSpec m il bl
CE.strikethroughSpec
        forall a. Semigroup a => a -> a -> a
<> forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il) =>
SyntaxSpec m il bl
CE.autolinkSpec
        forall a. Semigroup a => a -> a -> a
<> forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il, ToPlainText il) =>
SyntaxSpec m il bl
CE.autoIdentifiersSpec
        forall a. Semigroup a => a -> a -> a
<> forall (m :: Type -> Type) il bl.
(Monad m, IsBlock il bl, IsInline il, HasTaskList il bl) =>
SyntaxSpec m il bl
CE.taskListSpec