[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.
Re: Introducing emacs-webkit and more thoughts on Emacs rendering (was Rethinking the design of xwidgets), Lars Ingebrigtsen, 2020/11/23