{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeOperators #-}

-- | Description: Parser for jQuery/CSS selector syntax
--
-- This module provides functions for parsing jQuery/CSS selectors into
-- 'Axis' functions.
--
-- The following selectors are currently supported:
--
-- - __Any selector__ (@*@): Select any node.
-- - __Element name selector__ (@div@): Select all elements of the given
--   element name.
-- - __Descendant selector__ (@a b@): Select /descendants/ of all the nodes
--   matching the LHS selector that match the RHS selector.
-- - __Child selector__ (@a > b@): Select /children/ of all the nodes
--   matching the LHS selector that match the RHS selector.
-- - __Following sibling selector__ (@a ~ b@): Select /siblings/ of all the
--   nodes matching the LHS selector that match the RHS selector.
-- - __Adjacent sibling selector__ (@a + b@):
--   Select /directly adjacent siblings/ of all the nodes matching the LHS
--   selector that match the RHS selector.
-- - __Alternative selector__ (@a , b@): Select all nodes that match the LHS
--   selector, and also all the nodes that match the RHS selector.
-- - __Class selector__ (@.classname@): Select all elements whose @class@
--   attribute contains the given class name.
-- - __ID selector__ (@#id@): Select the element whose @id@ attribute matches
--   the given ID. Note that while in a well-formed XML document, each ID may
--   only be used once, this selector will happily return multiple nodes if the
--   target document is not well-formed, or when it is combined with other
--   selectors that cause the same element to be matched via multiple paths
--   (see also the note below).
-- - __Attribute-exists selector__ (@[attr]@): Select elements that have an
--   attribute of the given name.
-- - __Attribute-is selector__ (@[attr="value"]@): Select elements whose @attr@
--   attribute is exactly equal to the given value.
-- - __Attribute-is-not selector__ (@[attr!="value"]@): Select elements whose
--   @attr@ attribute is not exactly equal to the given value.
-- - __Attribute-starts-with selector__ (@[attr^="value"]@): Select elements whose @attr@
--   attribute begins with the given value.
-- - __Attribute-ends-with selector__ (@[attr$="value"]@): Select elements whose @attr@
--   attribute ends with the given value.
-- - __Attribute-contains selector__ (@[attr*="value"]@): Select elements whose @attr@
--   attribute contains the given value.
-- - __Attribute-contains-word selector__ (@[attr~="value"]@): Select elements
--   whose @attr@ attribute contains the given value between word boundaries.
--   Word boundaries are the very beginning and end of the value, as well as
--   any nonzero number of whitespace characters.
-- - __Attribute-contains-prefix selector__ (@[attr|="value"]@): Select elements whose @attr@
--   attribute contains the given value as a prefix. A prefix is either the
--   entire value itself, or the given value plus a hyphen-minus character
--   (@-@) at the very beginning of the attribute value.
-- - __Not selector__ (@:not(a)@): Select all elements that do not match the
--   argument selector.
-- - __Has selector__ (@:has(a)@): Select all elements that have relatives
--   that match the argument selector. A relationship (@+@, @~@, @>@) can be
--   given at the start of the argument; if none is given, the /descendant/
--   relationship is the default.
-- - __First-child selector__ (@:first-child@): Select all elements that are
--   the first child of their respective parent.
-- - __Last-child selector__ (@:last-child@): Select all elements that are
--   the last child of their respective parent.
-- - __Nth-child selector__ (@:nth-child(n)@): Select all elements that are
--   the n-th child (1-based) of their respective parent.
-- - __Nth-last-child selector__ (@:nth-last-child(n)@): Select all elements
--   that are the n-th last child (1-based) of their respective parent.
--
-- __Note__: The way the 'Axis' and 'Cursor' types work, we cannot avoid
-- matching the same node multiple times - this is mainly because there is no
-- 'Eq' instance for 'Cursor', and thus we cannot remove duplicate matches from
-- the output of an 'Axis'. For example, the element @\<div id="foo"/\>@ would
-- match twice on the selector @div,#foo@: once because it matches the element
-- name @"div"@, and once because it matches the ID @"foo"@.
--
-- Depending on your needs, you may wish to either carefully design your
-- selectors to avoid this, or to cull the results yourself, using a reasonable
-- notion of equality.
module Text.XML.Selectors.Parsers.JQ
( jq
, jqFile
, jqFile'
, jqString
, jqText
, jqString'
, jqText'
, errorBundlePretty
)
where

import Text.Megaparsec
import Text.Megaparsec.Char
import Data.Text (Text)
import qualified Data.Text as Text
import qualified Data.Text.IO as Text
import Text.XML.Selectors.Types
import Text.XML (Name)
import Data.String (IsString, fromString)
import Data.Char (isAlphaNum, isDigit)

-- | Parse from a stream, error information in 'Left' on failure.
jq :: (IsString (Tokens s), Stream s, Token s ~ Char)
    => String -- ^ Name of source file
    -> s -- ^ Input stream
    -> Either (ParseErrorBundle s Text) Selector
jq :: forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
String -> s -> Either (ParseErrorBundle s Text) Selector
jq = forall e s a.
Parsec e s a -> String -> s -> Either (ParseErrorBundle s e) a
parse forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
jqSelector

-- | Parse from an unnamed 'String' input stream, error information in 'Left' on failure.
jqString :: String -- ^ Input stream
         -> Either (ParseErrorBundle String Text) Selector
jqString :: String -> Either (ParseErrorBundle String Text) Selector
jqString = forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
String -> s -> Either (ParseErrorBundle s Text) Selector
jq String
"<input>"

-- | Parse from an unnamed 'String' input stream, 'error' on failure.
jqString' :: String -- ^ Input stream
          -> Selector
jqString' :: String -> Selector
jqString' = forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall a. HasCallStack => String -> a
error forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s e.
(VisualStream s, TraversableStream s, ShowErrorComponent e) =>
ParseErrorBundle s e -> String
errorBundlePretty) forall a. a -> a
id forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
String -> s -> Either (ParseErrorBundle s Text) Selector
jq String
"<input>"

-- | Parse from an unnamed 'Text' input stream, error information in 'Left' on failure.
jqText :: Text -- ^ Input stream
       -> Either (ParseErrorBundle Text Text) Selector
jqText :: Text -> Either (ParseErrorBundle Text Text) Selector
jqText = forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
String -> s -> Either (ParseErrorBundle s Text) Selector
jq String
"<input>"

-- | Parse from an unnamed 'Text' input stream, 'error' on failure.
jqText' :: Text -- ^ Input stream
        -> Selector
jqText' :: Text -> Selector
jqText' = forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall a. HasCallStack => String -> a
error forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s e.
(VisualStream s, TraversableStream s, ShowErrorComponent e) =>
ParseErrorBundle s e -> String
errorBundlePretty) forall a. a -> a
id forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
String -> s -> Either (ParseErrorBundle s Text) Selector
jq String
"<input>"

-- | Parse from a file input stream, error information in 'Left' on failure.
jqFile :: FilePath
       -> IO (Either (ParseErrorBundle Text Text) Selector)
jqFile :: String -> IO (Either (ParseErrorBundle Text Text) Selector)
jqFile String
fn = do
  forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
String -> s -> Either (ParseErrorBundle s Text) Selector
jq String
fn forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO Text
Text.readFile String
fn

-- | Parse from a file input stream, throw a 'UserError' in 'IO' on failure.
jqFile' :: FilePath
        -> IO Selector
jqFile' :: String -> IO Selector
jqFile' String
fn =
  String -> IO (Either (ParseErrorBundle Text Text) Selector)
jqFile String
fn forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s e.
(VisualStream s, TraversableStream s, ShowErrorComponent e) =>
ParseErrorBundle s e -> String
errorBundlePretty) forall (m :: * -> *) a. Monad m => a -> m a
return


instance ShowErrorComponent Text where
  showErrorComponent :: Text -> String
showErrorComponent = Text -> String
Text.unpack

jqSelector :: (IsString (Tokens s), Stream s, Token s ~ Char) => Parsec Text s Selector
jqSelector :: forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
jqSelector = forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
space forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
choices forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
space forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s (m :: * -> *). MonadParsec e s m => m ()
eof

choices :: (IsString (Tokens s), Stream s, Token s ~ Char) => Parsec Text s Selector
choices :: forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
choices = do
  [Selector]
xs <- forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
item forall (m :: * -> *) a sep. MonadPlus m => m a -> m sep -> m [a]
`sepBy` (forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
space forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
',' forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
space)
  case [Selector]
xs of
    [] -> forall (m :: * -> *) a. Monad m => a -> m a
return Selector
None
    [Selector
x] -> forall (m :: * -> *) a. Monad m => a -> m a
return Selector
x
    [Selector]
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ [Selector] -> Selector
Choice [Selector]
xs

item :: (IsString (Tokens s), Stream s, Token s ~ Char) => Parsec Text s Selector
item :: forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
item = do
  Selector
what <- forall (m :: * -> *) a. Alternative m => a -> m a -> m a
option Selector
Any (forall s. (Stream s, Token s ~ Char) => Parsec Text s Selector
anyElem forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try forall s. (Stream s, Token s ~ Char) => Parsec Text s Selector
elemName)
  [Selector]
qualifiers <- forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
qualifier
  Maybe Selector
mcont <- forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
continuation
  let self :: Selector
self = forall a. Monoid a => [a] -> a
mconcat (Selector
what forall a. a -> [a] -> [a]
: [Selector]
qualifiers)
  case Maybe Selector
mcont of
    Maybe Selector
Nothing -> forall (f :: * -> *) a. Applicative f => a -> f a
pure Selector
self
    Just Selector
cont -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ Selector
self forall a. Semigroup a => a -> a -> a
<> Selector
cont

anyElem :: (Stream s, Token s ~ Char) => Parsec Text s Selector
anyElem :: forall s. (Stream s, Token s ~ Char) => Parsec Text s Selector
anyElem = forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'*' forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall (f :: * -> *) a. Applicative f => a -> f a
pure Selector
Any

elemName :: (Stream s, Token s ~ Char) => Parsec Text s Selector
elemName :: forall s. (Stream s, Token s ~ Char) => Parsec Text s Selector
elemName = Name -> Selector
Elem forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall n s.
(IsString n, Stream s, Token s ~ Char) =>
Parsec Text s n
name

name :: (IsString n, Stream s, Token s ~ Char) => Parsec Text s n
name :: forall n s.
(IsString n, Stream s, Token s ~ Char) =>
Parsec Text s n
name = forall a. IsString a => String -> a
fromString forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
some forall s. (Stream s, Token s ~ Char) => Parsec Text s Char
nameChar

nameChar :: (Stream s, Token s ~ Char) => Parsec Text s Char
nameChar :: forall s. (Stream s, Token s ~ Char) => Parsec Text s Char
nameChar = forall e s (m :: * -> *).
MonadParsec e s m =>
(Token s -> Bool) -> m (Token s)
satisfy Char -> Bool
isNameChar

isNameChar :: Char -> Bool
isNameChar :: Char -> Bool
isNameChar Char
c = Char -> Bool
isAlphaNum Char
c Bool -> Bool -> Bool
|| (Char
c forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Char
'_', Char
'-'])

continuation :: (IsString (Tokens s), Stream s, Token s ~ Char) => Parsec Text s Selector
continuation :: forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
continuation = forall (f :: * -> *) (m :: * -> *) a.
(Foldable f, Alternative m) =>
f (m a) -> m a
choice
  [ forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
child
  , forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
sibling
  , forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
nextSibling
  , forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
descendant
  ]

descendant :: (IsString (Tokens s), Stream s, Token s ~ Char) => Parsec Text s Selector
descendant :: forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
descendant = forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
space1 forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ((Selector
Descendant forall a. Semigroup a => a -> a -> a
<>) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
item)

child :: (IsString (Tokens s), Stream s, Token s ~ Char) => Parsec Text s Selector
child :: forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
child = forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
space forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'>' forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
space) forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ((Selector
Child forall a. Semigroup a => a -> a -> a
<>) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
item)

sibling :: (IsString (Tokens s), Stream s, Token s ~ Char) => Parsec Text s Selector
sibling :: forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
sibling = forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
space forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'~' forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
space) forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ((Selector
Sibling forall a. Semigroup a => a -> a -> a
<>) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
item)

nextSibling :: (IsString (Tokens s), Stream s, Token s ~ Char) => Parsec Text s Selector
nextSibling :: forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
nextSibling = forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
space forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'+' forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
space) forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ((Selector
NextSibling forall a. Semigroup a => a -> a -> a
<>) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
item)

qualifier :: (IsString (Tokens s), Stream s, Token s ~ Char) => Parsec Text s Selector
qualifier :: forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
qualifier = forall (f :: * -> *) (m :: * -> *) a.
(Foldable f, Alternative m) =>
f (m a) -> m a
choice
  [ forall s. (Stream s, Token s ~ Char) => Parsec Text s Selector
classAttrib
  , forall s. (Stream s, Token s ~ Char) => Parsec Text s Selector
idAttrib
  , forall s. (Stream s, Token s ~ Char) => Parsec Text s Selector
attribSelector
  , forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
firstChild
  , forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
nthChild
  , forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
nthLastChild
  , forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
having
  , forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
not_
  ]

classAttrib :: (Stream s, Token s ~ Char) => Parsec Text s Selector
classAttrib :: forall s. (Stream s, Token s ~ Char) => Parsec Text s Selector
classAttrib = do
  forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'.'
  Text
value <- forall n s.
(IsString n, Stream s, Token s ~ Char) =>
Parsec Text s n
name
  forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ AttribSelector -> Selector
Attrib (Name -> Text -> AttribSelector
AttribContainsWord Name
"class" Text
value)

idAttrib :: (Stream s, Token s ~ Char) => Parsec Text s Selector
idAttrib :: forall s. (Stream s, Token s ~ Char) => Parsec Text s Selector
idAttrib = do
  forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'#'
  Text
value <- forall n s.
(IsString n, Stream s, Token s ~ Char) =>
Parsec Text s n
name
  forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ AttribSelector -> Selector
Attrib (Name -> Text -> AttribSelector
AttribIs Name
"id" Text
value)

attribSelector :: (Stream s, Token s ~ Char) => Parsec Text s Selector
attribSelector :: forall s. (Stream s, Token s ~ Char) => Parsec Text s Selector
attribSelector = do
  forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'['
  Name
aname <- forall n s.
(IsString n, Stream s, Token s ~ Char) =>
Parsec Text s n
name
  Maybe (Name -> Text -> AttribSelector)
mop <- forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional forall s.
(Stream s, Token s ~ Char) =>
Parsec Text s (Name -> Text -> AttribSelector)
attribOp
  AttribSelector
asel <- case Maybe (Name -> Text -> AttribSelector)
mop of
    Maybe (Name -> Text -> AttribSelector)
Nothing -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ Name -> AttribSelector
AttribExists Name
aname
    Just Name -> Text -> AttribSelector
op -> Name -> Text -> AttribSelector
op Name
aname forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall n s.
(IsString n, Stream s, Token s ~ Char) =>
Parsec Text s n
quotedStr forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall n s.
(IsString n, Stream s, Token s ~ Char) =>
Parsec Text s n
name)
  forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
']'
  forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ AttribSelector -> Selector
Attrib AttribSelector
asel

attribOp :: (Stream s, Token s ~ Char) => Parsec Text s (Name -> Text -> AttribSelector)
attribOp :: forall s.
(Stream s, Token s ~ Char) =>
Parsec Text s (Name -> Text -> AttribSelector)
attribOp = forall (f :: * -> *) (m :: * -> *) a.
(Foldable f, Alternative m) =>
f (m a) -> m a
choice
  [ Name -> Text -> AttribSelector
AttribIs forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'=')
  , Name -> Text -> AttribSelector
AttribIsNot forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'!' forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'=')
  , Name -> Text -> AttribSelector
AttribStartsWith forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'^' forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'=')
  , Name -> Text -> AttribSelector
AttribEndsWith forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'$' forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'=')
  , Name -> Text -> AttribSelector
AttribContains forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'*' forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'=')
  , Name -> Text -> AttribSelector
AttribContainsWord forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'~' forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'=')
  , Name -> Text -> AttribSelector
AttribContainsPrefix forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'|' forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'=')
  ]

quotedStr :: (IsString v, Stream s, Token s ~ Char) => Parsec Text s v
quotedStr :: forall n s.
(IsString n, Stream s, Token s ~ Char) =>
Parsec Text s n
quotedStr = do
  Token s
quoteSym <- forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'"' forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'\''
  String
val <- forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many ((forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'\\' forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall e s (m :: * -> *).
MonadParsec e s m =>
(Token s -> Bool) -> m (Token s)
satisfy (forall a b. a -> b -> a
const Bool
True)) forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (forall e s (m :: * -> *).
MonadParsec e s m =>
(Token s -> Bool) -> m (Token s)
satisfy (forall a. Eq a => a -> a -> Bool
/= Token s
quoteSym)))
  Token s
_ <- forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Token s
quoteSym
  forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall a. IsString a => String -> a
fromString String
val

firstChild :: (IsString (Tokens s), Stream s, Token s ~ Char) => Parsec Text s Selector
firstChild :: forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
firstChild = Selector
FirstChild forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string Tokens s
":first-child") forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m ()
notFollowedBy forall s. (Stream s, Token s ~ Char) => Parsec Text s Char
nameChar

lastChild :: (IsString (Tokens s), Stream s, Token s ~ Char) => Parsec Text s Selector
lastChild :: forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
lastChild = Selector
LastChild forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string Tokens s
":last-child") forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m ()
notFollowedBy forall s. (Stream s, Token s ~ Char) => Parsec Text s Char
nameChar

nthChild :: (IsString (Tokens s), Stream s, Token s ~ Char) => Parsec Text s Selector
nthChild :: forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
nthChild = do
  Int -> Selector
NthChild forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string Tokens s
":nth-child") forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'(' forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
space forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall s. (Stream s, Token s ~ Char) => Parsec Text s Int
positiveInt forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
space forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
')')

nthLastChild :: (IsString (Tokens s), Stream s, Token s ~ Char) => Parsec Text s Selector
nthLastChild :: forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
nthLastChild = do
  Int -> Selector
NthChild forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Num a => a -> a
negate forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string Tokens s
":nth-last-child") forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'(' forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
space forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall s. (Stream s, Token s ~ Char) => Parsec Text s Int
positiveInt forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
space forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
')')

positiveInt :: (Stream s, Token s ~ Char) => Parsec Text s Int
positiveInt :: forall s. (Stream s, Token s ~ Char) => Parsec Text s Int
positiveInt = forall a. Read a => String -> a
read forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
some forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m (Token s)
digitChar

having :: (IsString (Tokens s), Stream s, Token s ~ Char) => Parsec Text s Selector
having :: forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
having = forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string Tokens s
":has") forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
space forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'(' forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (Selector -> Selector
Having forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
item) forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
')'

not_ :: (IsString (Tokens s), Stream s, Token s ~ Char) => Parsec Text s Selector
not_ :: forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
not_ = forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string Tokens s
":not") forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
space forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
'(' forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (Selector -> Selector
Not forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall s.
(IsString (Tokens s), Stream s, Token s ~ Char) =>
Parsec Text s Selector
item) forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
')'