{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}

module Scrappy.Scrape where

-- -- Basically just html patterns from testing / courtney market stuff
import Scrappy.Elem.Types (Elem', innerText')
import Scrappy.Elem.ElemHeadParse (hrefParser, parseOpeningTag)
import Scrappy.Elem.SimpleElemParser (el)
import Scrappy.Elem.ChainHTML ((</>>))
import Scrappy.Find (findNaive, findNaiveIO)
import Scrappy.Links (maybeUsefulUrl)
import Scrappy.Types

import Control.Monad.Trans.Maybe (MaybeT(..))
import Control.Monad.IO.Class (MonadIO)
import Data.Functor.Identity (Identity)
import Data.Either (fromRight)
import Data.Maybe (catMaybes, fromMaybe)
import Text.Parsec (Stream, ParsecT, parse, string, parserZero, anyChar, manyTill, char, many, try, runParserT)
import Control.Applicative (liftA2) 

type ScraperT a = ParsecT Html () Identity a 
---type Html = String


-- | Generate a scraping expression where when found, it will generate and link in a data structure
-- | to a relevant next pattern. For instance, an element of interest being found then switches the
-- | scraper expression to be a reference to itselfo
-- |
-- | for instance (el "a" [("id", "x")]) -> let ALPHANUM = document.select(this) -> someThingUsing ALPHANUM_MATCH
-- | in a statement --> which references [A, B, C] 
scrapeLinked :: ParsecT s u m a -> ParsecT s u m [String]
scrapeLinked :: forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m [String]
scrapeLinked = ParsecT s u m a -> ParsecT s u m [String]
forall a. HasCallStack => a
undefined


-- TODO(galen): move to Scrappy.Scrape
-- Generic function for dropping an abstract pattern from text 
filterFromTextP :: ScraperT a -> ScraperT String
filterFromTextP :: forall a. ScraperT a -> ScraperT String
filterFromTextP ScraperT a
p = (ScraperT a -> ParsecT String () Identity [a]
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
many (ScraperT a -> ScraperT a
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try ScraperT a
p)) ParsecT String () Identity [a]
-> ScraperT String -> ScraperT String
forall a b.
ParsecT String () Identity a
-> ParsecT String () Identity b -> ParsecT String () Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ((Char -> String -> String)
-> ParsecT String () Identity Char
-> ScraperT String
-> ScraperT String
forall a b c.
(a -> b -> c)
-> ParsecT String () Identity a
-> ParsecT String () Identity b
-> ParsecT String () Identity c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 (:) ParsecT String () Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar (ScraperT a -> ScraperT String
forall a. ScraperT a -> ScraperT String
filterFromTextP ScraperT a
p))

-- We can return a string since this will never fail
-- its provably impossible 
filterPattern :: String -> ScraperT a -> String
filterPattern :: forall a. String -> ScraperT a -> String
filterPattern String
txt ScraperT a
p = (ParseError -> String)
-> (String -> String) -> Either ParseError String -> String
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ParseError -> String
forall a. HasCallStack => a
undefined String -> String
forall a. a -> a
id (Either ParseError String -> String)
-> Either ParseError String -> String
forall a b. (a -> b) -> a -> b
$ ScraperT String -> String -> String -> Either ParseError String
forall s t a.
Stream s Identity t =>
Parsec s () a -> String -> s -> Either ParseError a
parse (ScraperT a -> ScraperT String
forall a. ScraperT a -> ScraperT String
filterFromTextP ScraperT a
p) String
"" String
txt 



-- | Super common case analysis
coerceMaybeParser :: Maybe a -> ScraperT a
coerceMaybeParser :: forall a. Maybe a -> ScraperT a
coerceMaybeParser = \case
  Just a
a -> a -> ScraperT a
forall a. a -> ParsecT String () Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a
  Maybe a
Nothing -> ScraperT a
forall s u (m :: * -> *) a. ParsecT s u m a
parserZero


hoistMaybe :: Applicative m => Maybe a -> MaybeT m a 
hoistMaybe :: forall (m :: * -> *) a. Applicative m => Maybe a -> MaybeT m a
hoistMaybe = m (Maybe a) -> MaybeT m a
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (m (Maybe a) -> MaybeT m a)
-> (Maybe a -> m (Maybe a)) -> Maybe a -> MaybeT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe a -> m (Maybe a)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure


exists :: ScraperT a -> Html -> Bool 
exists :: forall a. ScraperT a -> String -> Bool
exists ScraperT a
p String
html = Bool -> ([a] -> Bool) -> Maybe [a] -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False (Bool -> [a] -> Bool
forall a b. a -> b -> a
const Bool
True) (Maybe [a] -> Bool) -> Maybe [a] -> Bool
forall a b. (a -> b) -> a -> b
$ ScraperT a -> String -> Maybe [a]
forall a. ParsecT String () Identity a -> String -> Maybe [a]
runScraperOnHtml ScraperT a
p String
html 

scrape :: ScraperT a -> Html -> Maybe [a]
scrape :: forall a. ParsecT String () Identity a -> String -> Maybe [a]
scrape = ParsecT String () Identity a -> String -> Maybe [a]
forall a. ParsecT String () Identity a -> String -> Maybe [a]
runScraperOnHtml

scrapeFirst' :: ScraperT a -> Html -> Maybe a
scrapeFirst' :: forall a. ScraperT a -> String -> Maybe a
scrapeFirst' ScraperT a
f String
h = case ScraperT a -> String -> Maybe [a]
forall a. ParsecT String () Identity a -> String -> Maybe [a]
scrape ScraperT a
f String
h of
                    Just (a
x:[a]
xs) -> a -> Maybe a
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return a
x
                    Maybe [a]
_ -> Maybe a
forall a. Maybe a
Nothing 


-- fmap head
getFirstSafe :: Maybe [a] -> Maybe a
getFirstSafe :: forall a. Maybe [a] -> Maybe a
getFirstSafe (Just (a
x:[a]
_)) = a -> Maybe a
forall a. a -> Maybe a
Just a
x
getFirstSafe Maybe [a]
_ = Maybe a
forall a. Maybe a
Nothing


getFirstFitSafe :: (a -> Bool) -> Maybe [a] -> Maybe a
getFirstFitSafe :: forall a. (a -> Bool) -> Maybe [a] -> Maybe a
getFirstFitSafe a -> Bool
f (Just (a
x:[a]
xs)) = (a -> Bool) -> [a] -> Maybe a
forall a. (a -> Bool) -> [a] -> Maybe a
findFit a -> Bool
f (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
xs) 
getFirstFitSafe a -> Bool
_ Maybe [a]
_ = Maybe a
forall a. Maybe a
Nothing 

findFit :: (a -> Bool) -> [a] -> Maybe a
findFit :: forall a. (a -> Bool) -> [a] -> Maybe a
findFit a -> Bool
_ [] = Maybe a
forall a. Maybe a
Nothing
findFit a -> Bool
cond (a
x:[a]
xs) = if a -> Bool
cond a
x then a -> Maybe a
forall a. a -> Maybe a
Just a
x else (a -> Bool) -> [a] -> Maybe a
forall a. (a -> Bool) -> [a] -> Maybe a
findFit a -> Bool
cond [a]
xs 



-- | Find all occurences of a given parsing/scraping pattern
-- | e.g. getHtml' "https://google.ca" >>= return . runScraperOnHtml (el "a" []) , would give all 'a' tag html elements on google.ca  
runScraperOnHtml :: ParsecT String () Identity a -> String -> Maybe [a]
runScraperOnHtml :: forall a. ParsecT String () Identity a -> String -> Maybe [a]
runScraperOnHtml ParsecT String () Identity a
p String
html = Maybe [a] -> Either ParseError (Maybe [a]) -> Maybe [a]
forall b a. b -> Either a b -> b
fromRight Maybe [a]
forall a. Maybe a
Nothing (Either ParseError (Maybe [a]) -> Maybe [a])
-> Either ParseError (Maybe [a]) -> Maybe [a]
forall a b. (a -> b) -> a -> b
$ Parsec String () (Maybe [a])
-> String -> String -> Either ParseError (Maybe [a])
forall s t a.
Stream s Identity t =>
Parsec s () a -> String -> s -> Either ParseError a
parse (ParsecT String () Identity a -> Parsec String () (Maybe [a])
forall s (m :: * -> *) u a.
Stream s m Char =>
ParsecT s u m a -> ParsecT s u m (Maybe [a])
findNaive (ParsecT String () Identity a -> Parsec String () (Maybe [a]))
-> ParsecT String () Identity a -> Parsec String () (Maybe [a])
forall a b. (a -> b) -> a -> b
$ ParsecT String () Identity a
p) String
"" String
html 


runScraperOnHtmlIO :: (MonadIO m, Show a, Stream String m Char) => ParsecT String () m a -> String -> m (Maybe [a])
runScraperOnHtmlIO :: forall (m :: * -> *) a.
(MonadIO m, Show a, Stream String m Char) =>
ParsecT String () m a -> String -> m (Maybe [a])
runScraperOnHtmlIO ParsecT String () m a
p String
html = do
  Either ParseError (Maybe [a])
x <- ParsecT String () m (Maybe [a])
-> () -> String -> String -> m (Either ParseError (Maybe [a]))
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> u -> String -> s -> m (Either ParseError a)
runParserT (ParsecT String () m a -> ParsecT String () m (Maybe [a])
forall (m :: * -> *) s a u.
(MonadIO m, Stream s m Char, Show a) =>
ParsecT s u m a -> ParsecT s u m (Maybe [a])
findNaiveIO (ParsecT String () m a -> ParsecT String () m (Maybe [a]))
-> ParsecT String () m a -> ParsecT String () m (Maybe [a])
forall a b. (a -> b) -> a -> b
$ ParsecT String () m a
p) () String
"" String
html 
  Maybe [a] -> m (Maybe [a])
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe [a] -> m (Maybe [a])) -> Maybe [a] -> m (Maybe [a])
forall a b. (a -> b) -> a -> b
$ Maybe [a] -> Either ParseError (Maybe [a]) -> Maybe [a]
forall b a. b -> Either a b -> b
fromRight Maybe [a]
forall a. Maybe a
Nothing Either ParseError (Maybe [a])
x 

scrapeIO :: (MonadIO m, Show a, Stream String m Char) => ParsecT String () m a -> String -> m (Maybe [a])
scrapeIO :: forall (m :: * -> *) a.
(MonadIO m, Show a, Stream String m Char) =>
ParsecT String () m a -> String -> m (Maybe [a])
scrapeIO = ParsecT String () m a -> String -> m (Maybe [a])
forall (m :: * -> *) a.
(MonadIO m, Show a, Stream String m Char) =>
ParsecT String () m a -> String -> m (Maybe [a])
runScraperOnHtmlIO 

runScraperInBody :: ParsecT String () Identity a -> String -> Maybe [a]
runScraperInBody :: forall a. ParsecT String () Identity a -> String -> Maybe [a]
runScraperInBody ParsecT String () Identity a
prsr String
html = Maybe [a] -> Either ParseError (Maybe [a]) -> Maybe [a]
forall b a. b -> Either a b -> b
fromRight Maybe [a]
forall a. Maybe a
Nothing (Either ParseError (Maybe [a]) -> Maybe [a])
-> Either ParseError (Maybe [a]) -> Maybe [a]
forall a b. (a -> b) -> a -> b
$ Parsec String () (Maybe [a])
-> String -> String -> Either ParseError (Maybe [a])
forall s t a.
Stream s Identity t =>
Parsec s () a -> String -> s -> Either ParseError a
parse (ParsecT String () Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
skipToInBody ParsecT String () Identity ()
-> Parsec String () (Maybe [a]) -> Parsec String () (Maybe [a])
forall a b.
ParsecT String () Identity a
-> ParsecT String () Identity b -> ParsecT String () Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ParsecT String () Identity a -> Parsec String () (Maybe [a])
forall s (m :: * -> *) u a.
Stream s m Char =>
ParsecT s u m a -> ParsecT s u m (Maybe [a])
findNaive ParsecT String () Identity a
prsr) String
"" String
html

skipToInBody :: Stream s m Char => ParsecT s u m ()
skipToInBody :: forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
skipToInBody = ParsecT s u m Char -> ParsecT s u m Char -> ParsecT s u m String
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
manyTill ParsecT s u m Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar (Maybe [String]
-> [(String, Maybe String)] -> ParsecT s u m (String, Attrs)
forall s (m :: * -> *) u.
Stream s m Char =>
Maybe [String]
-> [(String, Maybe String)] -> ParsecT s u m (String, Attrs)
parseOpeningTag ([String] -> Maybe [String]
forall a. a -> Maybe a
Just [String
"html"]) [] ParsecT s u m (String, Attrs)
-> ParsecT s u m Char -> ParsecT s u m Char
forall a b. ParsecT s u m a -> ParsecT s u m b -> ParsecT s u m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Char -> ParsecT s u m Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'>')
               ParsecT s u m String
-> ParsecT s u m (Elem' String) -> ParsecT s u m (Elem' String)
forall s (m :: * -> *) u a b.
Stream s m Char =>
ParsecT s u m a -> ParsecT s u m b -> ParsecT s u m b
</>> String -> [(String, String)] -> ParsecT s u m (Elem' String)
forall s (m :: * -> *) u.
Stream s m Char =>
String -> [(String, String)] -> ParsecT s u m (Elem' String)
el String
"head" []
               ParsecT s u m (Elem' String)
-> ParsecT s u m (String, Attrs) -> ParsecT s u m (String, Attrs)
forall s (m :: * -> *) u a b.
Stream s m Char =>
ParsecT s u m a -> ParsecT s u m b -> ParsecT s u m b
</>> Maybe [String]
-> [(String, Maybe String)] -> ParsecT s u m (String, Attrs)
forall s (m :: * -> *) u.
Stream s m Char =>
Maybe [String]
-> [(String, Maybe String)] -> ParsecT s u m (String, Attrs)
parseOpeningTag ([String] -> Maybe [String]
forall a. a -> Maybe a
Just [String
"body"]) []
               ParsecT s u m (String, Attrs)
-> ParsecT s u m Char -> ParsecT s u m Char
forall a b. ParsecT s u m a -> ParsecT s u m b -> ParsecT s u m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Char -> ParsecT s u m Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'>'
               ParsecT s u m Char -> ParsecT s u m () -> ParsecT s u m ()
forall a b. ParsecT s u m a -> ParsecT s u m b -> ParsecT s u m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> () -> ParsecT s u m ()
forall a. a -> ParsecT s u m a
forall (m :: * -> *) a. Monad m => a -> m a
return () 

  
runScraperOnBody :: ParsecT String () Identity a -> String -> Maybe [a] 
runScraperOnBody :: forall a. ParsecT String () Identity a -> String -> Maybe [a]
runScraperOnBody ParsecT String () Identity a
prsr String
html = Maybe [a] -> Either ParseError (Maybe [a]) -> Maybe [a]
forall b a. b -> Either a b -> b
fromRight Maybe [a]
forall a. Maybe a
Nothing (Either ParseError (Maybe [a]) -> Maybe [a])
-> Either ParseError (Maybe [a]) -> Maybe [a]
forall a b. (a -> b) -> a -> b
$ Parsec String () (Maybe [a])
-> String -> String -> Either ParseError (Maybe [a])
forall s t a.
Stream s Identity t =>
Parsec s () a -> String -> s -> Either ParseError a
parse (ParsecT String () Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
skipToBody ParsecT String () Identity ()
-> Parsec String () (Maybe [a]) -> Parsec String () (Maybe [a])
forall a b.
ParsecT String () Identity a
-> ParsecT String () Identity b -> ParsecT String () Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ParsecT String () Identity a -> Parsec String () (Maybe [a])
forall s (m :: * -> *) u a.
Stream s m Char =>
ParsecT s u m a -> ParsecT s u m (Maybe [a])
findNaive ParsecT String () Identity a
prsr) String
"" String
html 

skipToBody :: Stream s m Char => ParsecT s u m ()
skipToBody :: forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
skipToBody = ParsecT s u m Char -> ParsecT s u m Char -> ParsecT s u m String
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
manyTill ParsecT s u m Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar (Maybe [String]
-> [(String, Maybe String)] -> ParsecT s u m (String, Attrs)
forall s (m :: * -> *) u.
Stream s m Char =>
Maybe [String]
-> [(String, Maybe String)] -> ParsecT s u m (String, Attrs)
parseOpeningTag ([String] -> Maybe [String]
forall a. a -> Maybe a
Just [String
"html"]) [] ParsecT s u m (String, Attrs)
-> ParsecT s u m Char -> ParsecT s u m Char
forall a b. ParsecT s u m a -> ParsecT s u m b -> ParsecT s u m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Char -> ParsecT s u m Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'>') ParsecT s u m String
-> ParsecT s u m (Elem' String) -> ParsecT s u m (Elem' String)
forall s (m :: * -> *) u a b.
Stream s m Char =>
ParsecT s u m a -> ParsecT s u m b -> ParsecT s u m b
</>> String -> [(String, String)] -> ParsecT s u m (Elem' String)
forall s (m :: * -> *) u.
Stream s m Char =>
String -> [(String, String)] -> ParsecT s u m (Elem' String)
el String
"head" [] ParsecT s u m (Elem' String)
-> ParsecT s u m () -> ParsecT s u m ()
forall a b. ParsecT s u m a -> ParsecT s u m b -> ParsecT s u m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> () -> ParsecT s u m ()
forall a. a -> ParsecT s u m a
forall (m :: * -> *) a. Monad m => a -> m a
return () 


runScraperOnHtml1 :: ParsecT String () Identity a -> String -> Maybe a
runScraperOnHtml1 :: forall a. ScraperT a -> String -> Maybe a
runScraperOnHtml1 ParsecT String () Identity a
p = (([a] -> a) -> Maybe [a] -> Maybe a
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [a] -> a
forall a. HasCallStack => [a] -> a
head) (Maybe [a] -> Maybe a)
-> (String -> Maybe [a]) -> String -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ParsecT String () Identity a -> String -> Maybe [a]
forall a. ParsecT String () Identity a -> String -> Maybe [a]
runScraperOnHtml ParsecT String () Identity a
p





-- {-# DEPRECATED simpleScrape' "from fba project - gives confusing String output" #-}
-- simpleScrape' :: ParsecT String () Identity String -> String -> String 
-- simpleScrape' p html = case parse (findNaive p) "" html of
--   Right (Just (x:_)) -> x
--   Right (Just []) -> "NothingA"
--   Right (Nothing) -> "NothingB"
--   Left err -> "Nothing" <> show err



-- clean :: String -> String
-- clean = undefined -- drop if == ( \n | \" | '\\' )


-- -- | uses maybeUsefulUrl to get all links on page pointing only to same site links
-- allLinks :: String -> ParsecT String () Identity [String] 
-- allLinks baseUrl = do
--   x <- findNaive hrefParser 
--   return $ case x of
--     Just (x':xs') -> catMaybes $ fmap (maybeUsefulUrl baseUrl) (x':xs')
--     Just [] -> []
--     Nothing -> [] 

-- type Name = String -- placeholder
-- tableItem :: Name -> Elem' String
-- tableItem = undefined




-- scrapeInnerText :: ParsecT String () Identity (Elem' String) -> String 
-- scrapeInnerText p = case parse (findNaive p) "" body of
--   Right (Just (x:_)) -> innerText' x
--   Right (Just []) -> "Nothing"
--   Right (Nothing) -> "Nothing"
--   Left err -> show err




scrapeFirst :: Stream s m Char => ParsecT s u m a -> ParsecT s u m (Maybe a)
scrapeFirst :: forall s (m :: * -> *) u a.
Stream s m Char =>
ParsecT s u m a -> ParsecT s u m (Maybe a)
scrapeFirst ParsecT s u m a
p = do
  Maybe [a]
x <- ParsecT s u m a -> ParsecT s u m (Maybe [a])
forall s (m :: * -> *) u a.
Stream s m Char =>
ParsecT s u m a -> ParsecT s u m (Maybe [a])
findNaive ParsecT s u m a
p
  case Maybe [a]
x of
    Just (a
x:[a]
_) -> Maybe a -> ParsecT s u m (Maybe a)
forall a. a -> ParsecT s u m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a -> ParsecT s u m (Maybe a))
-> Maybe a -> ParsecT s u m (Maybe a)
forall a b. (a -> b) -> a -> b
$ a -> Maybe a
forall a. a -> Maybe a
Just a
x
    Maybe [a]
Nothing -> Maybe a -> ParsecT s u m (Maybe a)
forall a. a -> ParsecT s u m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a -> ParsecT s u m (Maybe a))
-> Maybe a -> ParsecT s u m (Maybe a)
forall a b. (a -> b) -> a -> b
$ Maybe a
forall a. Maybe a
Nothing

 
findCount :: Stream s m Char => ParsecT s u m a -> ParsecT s u m Int
findCount :: forall s (m :: * -> *) u a.
Stream s m Char =>
ParsecT s u m a -> ParsecT s u m Int
findCount ParsecT s u m a
p = do
  Maybe [a]
x <- ParsecT s u m a -> ParsecT s u m (Maybe [a])
forall s (m :: * -> *) u a.
Stream s m Char =>
ParsecT s u m a -> ParsecT s u m (Maybe [a])
findNaive ParsecT s u m a
p
  Int -> ParsecT s u m Int
forall a. a -> ParsecT s u m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> ParsecT s u m Int) -> Int -> ParsecT s u m Int
forall a b. (a -> b) -> a -> b
$ [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([a] -> Maybe [a] -> [a]
forall a. a -> Maybe a -> a
fromMaybe [] Maybe [a]
x)




type Prefix' = String
{-# DEPRECATED scrapeBracketed "experimental, first attempt" #-}
scrapeBracketed :: Prefix' -> ScraperT a -> Html -> Maybe [a]
scrapeBracketed :: forall a. String -> ScraperT a -> String -> Maybe [a]
scrapeBracketed String
pre ScraperT a
scraper String
html = [[a]] -> [a]
forall a. Monoid a => [a] -> a
mconcat ([[a]] -> [a]) -> Maybe [[a]] -> Maybe [a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ScraperT [a] -> String -> Maybe [[a]]
forall a. ParsecT String () Identity a -> String -> Maybe [a]
scrape (String -> ScraperT String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
pre ScraperT String -> ScraperT [a] -> ScraperT [a]
forall a b.
ParsecT String () Identity a
-> ParsecT String () Identity b -> ParsecT String () Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ScraperT a -> ScraperT String -> ScraperT [a]
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
manyTill ScraperT a
scraper (String -> ScraperT String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
pre)) String
html



type Prefix = String 
scrapePrefixed :: Prefix -> ScraperT a -> Html -> Maybe [a]
scrapePrefixed :: forall a. String -> ScraperT a -> String -> Maybe [a]
scrapePrefixed String
pre ScraperT a
scraper String
html = ScraperT a -> String -> Maybe [a]
forall a. ParsecT String () Identity a -> String -> Maybe [a]
scrape (String -> ScraperT String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
pre ScraperT String -> ScraperT a -> ScraperT a
forall a b.
ParsecT String () Identity a
-> ParsecT String () Identity b -> ParsecT String () Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ScraperT a
scraper) String
html