M src/Internal/Elements.hs => src/Internal/Elements.hs +3 -0
@@ 47,6 47,9 @@ find (Find "css selector" sel) root = case CSS.parsePath sel of
find (Find "link text" sel) root = Right $ allLinks (== pack sel) root
find (Find "partial link text" sel) root = Right $ allLinks (Txt.isInfixOf $ pack sel) root
find (Find "tag name" sel) root = Right (X.descendant root >>= X.checkName (== fromString sel))
+find (Find "xpath" sel) root = case XPath.runXPath root $ Txt.pack sel of
+ Right res -> Right res
+ Left msgs -> Left (True, Prelude.unlines msgs)
find (Find type_ _) _ = Left (False, "Invalid selector type: " ++ Txt.unpack type_)
allLinks test = X.descendant X.>=>
M src/Internal/Elements/XPath.hs => src/Internal/Elements/XPath.hs +13 -13
@@ 20,19 20,7 @@ import Text.Read (readMaybe)
data Context = Context {
item :: [Value],
vars :: M.Map Name [Value],
- funcs :: M.Map (Name, Int) (Context -> [[Value]] -> [Value]),
- timestamp :: ZonedTime,
- timezone :: TimeZone,
- lang :: Text,
- calendar :: Text,
- place :: Text, -- Noop?
- docs :: M.Map Name Document,
- texts :: M.Map Text Text,
- collections :: M.Map Text [Value],
- collection :: [Value],
- uriCollections :: M.Map Text [Text],
- uriCollection :: [Text],
- environment :: M.Map Text Text
+ funcs :: M.Map (Name, Int) (Context -> [[Value]] -> [Value])
}
---- Typesystem/coercion
@@ 565,3 553,15 @@ fnMathATan _ [x'] | Right x <- num x' = [Number $ atan x]
fnMathATan _ _ = typeError
fnMathATan2 _ [y', x'] | Right x <- num x', Right y <- num y' = [Number $ atan2 y x]
fnMathATan2 _ _ = typeError
+
+---- Public API
+runXPath' node sel = case parseXPath sel of
+ Right ast -> evals Context {
+ item = [Node node],
+ vars = M.empty,
+ funcs = stdLib
+ } ast
+ Left err -> [Error "err:syntax" err ""]
+runXPath node sel = let ret = runXPath' node sel
+ in if any isErr ret then Left [msg | Error name msg _ <- ret]
+ else Right [n | Node n <- ret]
M src/UI/Search.hs => src/UI/Search.hs +1 -0
@@ 28,6 28,7 @@ engines = [
(const "CSS", queryEls "css selector"),
(flip l LinkSearchExact, queryEls "link text"), -- Only useful if it promotes results higher.
(flip l LinkSearch, queryEls "partial link text")
+-- (const "XPath", queryEls "xpath") -- FIXME parser infinite loops...
]
result href' = a ! href (stringValue href') ! target "preview"