;;; ;;; REMOVE WEB ELEMENTS ------------------------------------------------ ;;; ;;; (open-file) ; a) select local file ;;; (open-url) ; b) enter URL ;;; (set-url "http://lisp.it") ; c) set URL directly ;;; ;;; (count* :img) ; count matching web elements ;;; (count* "*") ; see CSS2 selectors ;;; ;;; (strip :img) ; removes all ;;; (strip :div :id "main") ; removes
;;; (strip :a :rel "next") ; removes This is spam. ;;; ;;; optionally use CSS2 selector syntax: ;;; ;;; (strip "*") ; oops! (see context menu / reload) ;;; ;;; (view :div :id "main") ; displays "outerHtml" of single element ;;; ;;; (save-file) ;;; ;;; ;;; INSPECTOR ---------------------------------------------------------- ;;; ;;; (inspector) ; see context menu / inspect ;;; ;;; ;;; ITERATE ------------------------------------------------------------ ;;; ;;; (iterate-elements "A" (|setOuterXml| element text)) ; unlink ;;; #+win32 (si:trap-fpe 'floating-point-underflow nil) ; for QWebInspector (qrequire :webkit) (in-package :eql-user) (load "inspector") (defvar *web-view* (qnew "QWebView")) (defmacro iterate-elements (tag/selector &body body) "Iterates over web elements of QWebFrame, locally binding ELEMENT to QWebElement, and TEXT to its plain text." (let ((i (gensym))) `(let ((elements (|findAllElements| (frame) ,tag/selector))) (dotimes (,i (|count| elements)) (let* ((element (|at| elements ,i)) (text (|toPlainText| element))) ,@body))))) (defun set-url (name) (unless (x:empty-string name) (|setWindowTitle| *web-view* name) (x:do-with *web-view* (|load| (|fromUserInput.QUrl| name)) (|show|)))) (defun open-url () (let ((name (|getText.QInputDialog| *web-view* nil (tr "Enter URL:") |QLineEdit.Normal| "http://planet.lisp.org/" nil))) ; ok (when (qok) (set-url name)))) (let ((filter "Html files (*.htm *.html)")) (defun open-file () (set-url (|getOpenFileName.QFileDialog| nil nil nil filter))) (defun save-file () (let ((file (|getSaveFileName.QFileDialog| nil nil nil filter))) (unless (x:empty-string file) (with-open-file (s (x:path file) :direction :output :if-exists :supersede) (write-string (|toHtml| (frame)) s) file))))) (defun frame () (|mainFrame| (|page| *web-view*))) (defun to-string (x) (cond ((stringp x) x) ((keywordp x) (symbol-name x)) (t "*"))) (defun count* (&optional (tag/selector "*")) (|count| (|findAllElements| (frame) (to-string tag/selector)))) (defun strip (tag/selector &optional attribute value) "Removes all web elements matching tag/selector. Returns number of removed elements." (let ((removed 0)) (flet ((rm (el) (incf removed) (|removeFromDocument| el))) (let ((attr (to-string attribute))) (iterate-elements (to-string tag/selector) (if (eql :text attribute) (when (search value text :test 'string-equal) (rm element)) (when (or (not attribute) (string-equal value (|attribute| element attr))) (rm element)))))) removed)) (defun web-view-dialog (html) "Displays html in temporary dialog." (qlet ((dialog "QDialog") (layout "QVBoxLayout(QWidget*)" dialog) (view "QWebView")) (|addWidget| layout view) (|setHtml| view html) (|exec| dialog))) ; delete on closing (see QLET) (defun view (tag/selector &optional attribute value) "Displays 'outerHtml' of first tag/selector found." (flet ((view* (el) (web-view-dialog (|toOuterXml| el)) (return-from view))) (let ((attr (to-string attribute))) (iterate-elements (to-string tag/selector) (if (eql :text attribute) (when (search value text :test 'string-equal) (view* element)) (when (or (not attribute) (string-equal value (|attribute| element attr))) (view* element))))))) (open-url)