emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Introducing emacs-webkit and more thoughts on Emacs rendering (was R


From: Akira Kyle
Subject: Re: Introducing emacs-webkit and more thoughts on Emacs rendering (was Rethinking the design of xwidgets)
Date: Sun, 22 Nov 2020 20:44:16 -0700
User-agent: mu4e 1.4.13; emacs 28.0.50


On Sun, Nov 22, 2020 at 05:46 PM, T.V Raman <raman@google.com> wrote:

Doing the manipulation with injected jSON would be fin e bye me.

I did look at parenscript in the context of nyxt,
and it looks interesting, but I dont have anything religious re the
shape of delimiters I use to write code :-)

My interest stems primarily from wanting to speak Web content
intelligently and EWW gets me a lot of that, except where Web Content is dynamically generated from JS and given that, I'm looking to get Webkit to build the DOM, and give it to me in a form that I can query
it, manipulate it, and finally speak the relevant bits.

Here's a proof of concept of that. Don't try it on any large or complicated page as it'll grind Emacs to a halt trying to do the parsing.
(setq webkit--to-json-js "
function toJSON(node) {
 let propFix = { for: 'htmlFor', class: 'className' };
 let specialGetters = {
   style: (node) => node.style.cssText,
 };
 let attrDefaultValues = { style: '' };
 let obj = {
   nodeType: node.nodeType,
 };
 if (node.tagName) {
   obj.tagName = node.tagName.toLowerCase();
 } else if (node.nodeName) {
   obj.nodeName = node.nodeName;
 }
 if (node.nodeValue) {
   obj.nodeValue = node.nodeValue;
 }
 let attrs = node.attributes;
 if (attrs) {
   let defaultValues = new Map();
   for (let i = 0; i < attrs.length; i++) {
     let name = attrs[i].nodeName;
     defaultValues.set(name, attrDefaultValues[name]);
   }
// Add some special cases that might not be included by enumerating // attributes above. Note: this list is probably not exhaustive.
   switch (obj.tagName) {
     case 'input': {
       if (node.type === 'checkbox' || node.type === 'radio') {
         defaultValues.set('checked', false);
       } else if (node.type !== 'file') {
         // Don't store the value for a file input.
         defaultValues.set('value', '');
       }
       break;
     }
     case 'option': {
       defaultValues.set('selected', false);
       break;
     }
     case 'textarea': {
       defaultValues.set('value', '');
       break;
     }
   }
   let arr = [];
   for (let [name, defaultValue] of defaultValues) {
     let propName = propFix[name] || name;
     let specialGetter = specialGetters[propName];
let value = specialGetter ? specialGetter(node) : node[propName];
     if (value !== defaultValue) {
       arr.push([name, value]);
     }
   }
   if (arr.length) {
     obj.attributes = arr;
   }
 }
 let childNodes = node.childNodes;
// Don't process children for a textarea since we used `value` above. if (obj.tagName !== 'textarea' && childNodes && childNodes.length) {
   let arr = (obj.childNodes = []);
   for (let i = 0; i < childNodes.length; i++) {
     arr[i] = toJSON(childNodes[i]);
   }
 }
 return obj;
}
toJSON(document);
")

(defun webkit--save-json (msg)
 (setq webkit--json (json-parse-string msg)))

(webkit--execute-js
(with-current-buffer (car webkit--buffers) webkit--id)
webkit--to-json-js "webkit--save-json")


I think through this general framework one could more efficiently extract the parts of the DOM one is interested in rather than dumping it all into elisp like I did above.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]