Trying this again... Bringing XML literals to NodeJS

79 de afișări
Accesați primul mesaj necitit

Marcel Laverdet

necitită,
16 dec. 2010, 13:02:1016.12.2010
– nodejs
I posted last month about my work bringing E4X to NodeJS (and elsewhere) via desugaring [http://groups.google.com/group/nodejs/browse_thread/thread/713067d9d9db64e7], and since then I've been taking the project in a different direction. I'm pretty much abandoning E4X entirely, and only implementing XML literals as if E4X didn't exist. This idea came up in another thread last month too [http://groups.google.com/group/nodejs/browse_thread/thread/835e9cbef4e96174].

So I stripped out all the E4X static analysis and runtime and left only support for XML literals. I also defined a very basic interface for working with XML literals which lets you use XML to construct whatever objects you want.

Included is a basic pseudo-DOM implementation which should be good for most purposes (read: my purposes). But the beauty is that you can use XML literals on top of a more full-featured library like jsdom, or even on the client-side on top of the browser's native DOM.

Here's some examples of what we can do now:

marcel@marcel $ cat example.js 
var u = require('util');

var div = <div>Click <a href="/something">here</a> to see something.</div>;
div.className = 'description';
u.log(div);

var untrusted_user_input = '<script>alert("xss!")</script>';
div = <div>{untrusted_user_input}</div>;
u.log(div);

var frag = <><li>one</li><li>two</li><li>three</li></>;
u.log(frag.toString());
u.log(<ol>{frag}</ol>);
u.log(frag);

marcel@marcel $ ./quick-run example.js 
17 Dec 02:46:04 - <div class="description">Click <a href="/something">here</a> to see something.</div>
17 Dec 02:46:04 - <div>&lt;script&gt;alert("xss!")&lt;/script&gt;</div>
17 Dec 02:46:04 - <li>one</li><li>two</li><li>three</li>
17 Dec 02:46:04 - <ol><li>one</li><li>two</li><li>three</li></ol>
17 Dec 02:46:04 - 

This example is using the built-in simple DOM implementation, but it's easy enough to switch to jsdom if that's what you're in to:

var DOMXMLEnvironment = require('./runtime/dom-environment').DOMXMLEnvironment;
var dom = require('./jsdom/lib/jsdom/level2/core').dom.level2.core;
XMLEnvironment.set(new DOMXMLEnvironment(new dom.Document()));

From here on out any XML literals created will use the jsdom document you created.

For those of you who are curious here's an example of what the desugared code looks like--

Original: <node>Text <inner-node /></node>
Desugared: XMLEnvironment.get()._el({"type": 1, "open": "node", "close": "node", "attributes": void 0, "content": [{"type": 2, "value": "Text "}, {"type": 1, "open": "inner-node", "close": void 0, "attributes": void 0, "content": void 0}]});

That's about where the project is now. I wanted to see if any opinions have been changed since I shifted the focus of the project. E4X was pretty ridiculous and I think abandoning the spec was the right move. I think XML literals will be an extremely valuable tool for NodeJS developers who choose to embrace them.

Marcel Laverdet

necitită,
16 dec. 2010, 13:03:2216.12.2010
– nodejs
Of course I forget the link to the project!

Elijah Insua

necitită,
16 dec. 2010, 13:20:3416.12.2010
– nod...@googlegroups.com
I can see this being sort of beneficial if the inline XML could be multi-line but to be completely honest, if you have huge chunks of html/xml mixed with your js you may be doing something wrong.

-- Elijah

On Thu, Dec 16, 2010 at 1:03 PM, Marcel Laverdet <mar...@laverdet.com> wrote:
Of course I forget the link to the project!

--
You received this message because you are subscribed to the Google Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com.
To unsubscribe from this group, send email to nodejs+un...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/nodejs?hl=en.

Marcel Laverdet

necitită,
16 dec. 2010, 13:36:4116.12.2010
– nod...@googlegroups.com
Of course it can be multiline. The whitespace normalization logic needs a little work, though.

marcel@marcel $ cat lines.js 
var foo = <div>
  <span>Hello</span>
</div>;
require('util').print(foo + '\n');

marcel@marcel $ ./quick-run lines.js 
<div> <span>Hello</span>
</div>

Also heavy use of XML literals doesn't imply you're doing something wrong. There's nothing saying you can't use a subset of Javascript + XML literals as a template library. As with any tool it can be misused, but if you're going to misuse XML literals you could also just misuse raw strings with markup. Also worth keeping in mind, is that MVC isn't necessarily the only one right way to design software, it's just one good way; but that's way out of scope for this thread ;)

Ryan Gahl

necitită,
16 dec. 2010, 13:39:1516.12.2010
– nod...@googlegroups.com
Love it!!

Liam

necitită,
16 dec. 2010, 14:17:0716.12.2010
– nodejs
Yes, that's very helpful and simple.

I only see one DOM call in your example, div.className = ...

Can you describe your DOM api a bit more?

Will you have interoperability with other Node xml tools?

Marcel Laverdet

necitită,
16 dec. 2010, 14:36:5016.12.2010
– nod...@googlegroups.com
Good point, I didn't show off too much of the DOM API. Though, the included DOM API is very spartan, but enough to build on top of. Supported (in no particular order):
methods: insertBefore, replaceChild, removeChild, appendChild, cloneNode (planned), hasChildNodes, setAttribute[NS], getAttribute[NS]
properties: nodeName, nodeValue, childNodes, parentNode, firstChild, lastChild, nextSibling, previousSibling, namespaceURI

And that's it. Also document fragments, and namespaces are supported. On top of that I defined HTML getters and setters for most of HTML5 and below. I may be missing some because my method was to just click everything on Mozilla's DOM documentation and implement any HTML accessor that wasn't moz-specific.

Of course if the included DOM doesn't suit your needs you can switch to jsdom.. I just feel that jsdom is quite meaty for my use cases. I will likely end up wanting to implement more of the HTMLElement utility functions like getElementsByTagName (minus live NodeList's), but for now this is good to work with.

As for interoperability, could you be a little more clear? You can define an XMLEnvironment to do whatever you want with XML literals. So if you want to use XML literals to mutate documents through another library it's just a matter of writing 4 methods (isNode, createElement, createFragment, createTextNode).

Răspundeți tuturor
Răspundeți autorului
Redirecționați
0 mesaje noi