diff options
Diffstat (limited to 'app/Issue/Parser.hs')
-rw-r--r-- | app/Issue/Parser.hs | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/app/Issue/Parser.hs b/app/Issue/Parser.hs new file mode 100644 index 0000000..b7cfa4b --- /dev/null +++ b/app/Issue/Parser.hs @@ -0,0 +1,61 @@ +module Issue.Parser + ( ParseResult (..), + parse, + ) +where + +import CMark qualified as D +import Control.Exception (throw) +import Control.Monad (liftM2) +import Data.Text qualified as T +import Data.Void (Void) +import Exception qualified as E +import Text.Megaparsec qualified as P + +data ParseResult = ParseResult + { heading :: D.Node, + paragraphs :: [D.Node], + tags :: [D.Node], + comments :: [[D.Node]] + } + deriving (Show) + +parse :: [T.Text] -> D.Node -> Maybe ParseResult +parse markers (D.Node _ D.DOCUMENT ns) = + either (throw . E.InvalidIssue) id $ + P.parse (parser markers) "" ns +parse _ _ = error "parse: input is no markdown document" + +parser :: [T.Text] -> P.Parsec Void [D.Node] (Maybe ParseResult) +parser markers = + P.optional (P.satisfy (isMarkerNode markers)) >>= \case + Just heading -> + Just + <$> ( ParseResult heading + <$> P.takeWhileP + Nothing + (not . liftM2 (||) isCommentNode isTagNode) + <*> P.takeWhileP Nothing isTagNode + <*> P.many + ( (:) + <$> P.satisfy isCommentNode + <*> P.takeWhileP Nothing (not . isCommentNode) + ) + <* P.eof + ) + Nothing -> pure Nothing + +isCommentNode :: D.Node -> Bool +isCommentNode (D.Node _ D.PARAGRAPH (D.Node _ (D.TEXT s) _ : _)) = + "COMMENT" `T.isPrefixOf` s +isCommentNode _ = False + +isTagNode :: D.Node -> Bool +isTagNode (D.Node _ D.PARAGRAPH (D.Node _ (D.TEXT s) _ : _)) = + "@" `T.isPrefixOf` s +isTagNode _ = False + +isMarkerNode :: [T.Text] -> D.Node -> Bool +isMarkerNode markers (D.Node _ D.PARAGRAPH (D.Node _ (D.TEXT s) _ : _)) = + any (`T.isPrefixOf` s) markers +isMarkerNode _ _ = False |