(in-package #:oh-ducks) (named-readtables:in-readtable template-readtable) ;; FIXME: the switch to chtml:pt nodes means our #'equalp no longer ;; works. #+(or) (setq *default-parser* 'pt) (equalp '(:div ((:id "id")) "I " (:i () "like") " cheese.") (match (#T(html (:model lhtml) ("#id" . ?div)) "
I like cheese.
") ;; FIXME: learn to distinguish between when there should only be one ;; result and when there should be many? (car div))) (equalp '((:div ((:class "red fish")) "one fish") (:div ((:class "blue fish")) "two fish")) (match (#T(html (:model lhtml) (".fish" . ?divs) (".pig" . ?pig)) "
bricklayer
one fish
two fish
") ;; pig doesn't affect the equalp...but does show separate things are separate (values divs pig))) (equalp '((:i () "not") (:i () "cheese")) (match (#T(html (:model lhtml) ("div" ("i" . ?i))) "
I do not like cheese.
I like cheese.
") i)) (equalp '((:i () "not")) (match (#T(html (:model lhtml) ("div>i" . ?i)) "
I do not like cheese.
I like cheese.
") i)) (equalp '((:i () "not")) (match (#T(html (:model lhtml) ("div" (">i" . ?i) ;("i" . #t(list ?j ?i)) ("span>i" . ?span))) "
I do not like cheese.
I like cheese.
") (values i span))) (defun make-dom-document (child-node) (make-instance 'rune-dom::document :children (rune-dom::make-node-list (list child-node)))) (defun serialize (object) (let ((document (etypecase object (rune-dom::document object) (rune-dom::element (make-dom-document object)) (chtml:pt object) (list object)))) (etypecase document (rune-dom::document (dom:map-document (cxml:make-string-sink :omit-xml-declaration-p t) document)) (chtml:pt (chtml:serialize-pt document (chtml:make-string-sink))) (list (mapcar #'serialize document))))) (defmacro serialize-values (form) `(let ((values (multiple-value-list ,form))) (values-list (mapcar #'serialize values)))) (equal '("cheese" "cheese") (serialize-values (match (#T(html (:model dom) ("i" . #t(list ?j ?i)) ("span>i" . ?span)) "
I do not like cheese.
I like cheese.
") (values i span)))) (serialize-values (match (#T(html (:model dom) ("div:first-child" . ?div) ("i:nth-child(1)" . ?i)) "
I do not like cheese.
I like cheese.
") (values div i))) (serialize-values (match (#T(html (:model dom) ("div:nth-last-child(1)" . ?div) ("div:last-child" . ?d2)) "
I do not like cheese.
I like cheese.
") (values div d2))) (serialize-values (match (#t(html (:model dom) (":nth-last-of-type(2)" . ?first) (":nth-of-type(2)" . ?last)) "
1i2i
") (values first last))) (match (#T(html (:model dom) ("q" . ?div)) "
I do not like cheese.
I like cheese.
") (values div)) ;; throws 'unification-failure (serialize-values (match (#T(html (:model dom) ("i:only-child" . ?i) ("i:only-of-type" . ?i-type)) "
I do not like cheese.
I like cheese.
") (values i i-type))) (serialize-values (match (#T(html (:model dom) ("b + i" . ?i)) "
I really like cheese. Do you not dislike cheese?
") (values i))) (serialize-values (match (#T(html (:model dom) ("b ~ i" . ?i)) "
I really like cheese. Do you not dislike cheese?
") (values i))) (serialize-values (match (#T(html (:model pt) ("body :empty" . ?empty)) "


testingitesting

") (values empty))) ;; Sometimes, you want to match a thing inside a thing, in which case ;; combinators should implicitly assume an unspecified right side means ;; "whatever element I gave you". (serialize-values (match (#T(html (:model dom) ("q" . ?q)) "
ham foo bar baz quuz spam
") (match (#t(html ("> i" . ?i)) (first q)) i))) ;; siblings will also match, thanks to a bit of ugly code (serialize-values (match (#T(html (:model dom) ("q" . ?q)) "
ham foo bar baz quuz spamnot match
") (match (#t(html ("+ i" . ?i)) (first q)) i))) (serialize-values (match (#T(html (:model dom) ("q" . ?q)) "
foo outer q baz inner q quuz
") (match (#t(html ("q" . ?i)) (first q)) i))) (serialize-values (match (#T(html (:model dom) ("[id]" . ?ids)) "
blank idfoono idbarid id
") ids)) (serialize-values (match (#T(html (:model dom) ("[id=foo]" . ?id)) "
bar idno idfoo id
") id)) #+LATER? (match (#t(html ("div::content" . #t(regexp+ "^f(o+)" (?o)))) "
barbaz
fooooooobar
") (values o &rest))