Closed bitinn closed 9 years ago
Mostly using dom-layer
for my own curiosity, trying to write a module that convert my existing virtual-dom
templates into dom-layer
templates without changing my existing codes, and I do have inline style and javascript :)
Not sure to get what you mean. If you have some inline javascript or style you can simply create them using Tag
directly https://jsfiddle.net/oty2unoo/
Makes sense ?
Btw why did you left virtual-dom
? And is the project you are working on is an open source project ? just curious ;-)
I haven't left virtual-dom, just trying out new vdom implementation :)
Maybe I didn't fully understand your Text
definition, normally one would expect Text
to escape its input, so inline javascript won't work (otherwise xss)
The Text
node is identical to the virtual dom VText
node. So there's no reason to have possible XSS using Text
. For example:
new Tag("div", {}, [new Text("<b>hello world</b>")]);
generates the following text content "<b>hello world</b>"
(i.e all markups will be interpreted as text and not html)
However, you need to pay attention if you are using the innerHTML
property to set a tag content:
new Tag("div", { props: { innerHTML: "<b>hello world</b>"} });
In this case it will render "hello world" in bold. So using innerHTML
may open rooms for some XSS exploits.
@jails Then my question is how does one do innerHTML
on server-side? using attrs: { innerHTML: ... }
only put them as literal attributes, and as you mentioned props: { innerHTML: ... }
is empty. I do need to render inline content (be it html, css, javascript) server-side without being escaped automatically.
Just to add, I was trying to make my virtual-dom
templates compatible with dom-layer
, like I did with deku
:
https://gist.github.com/bitinn/ca83c32f041f89e4e5ad
But dom-layer
Tag and Text api appear to be even more restrictive than deku
, so I haven't had a full implementation for it yet.
In longrun though, I think making dom-layer
api closer to virtual-dom
and deku
may help ppl adopt this module, I think it's core support for server-side rendering and progressive enhancement (ie. .attach
) may prove to be very useful.
similar discussion on deku https://github.com/dekujs/deku/issues/164
Just to clear things up, attributes carry additional informations about HTML elements. And it can be defined through an HTML template using some name="value"
pairs. Example: <div class="my-class"></div>
. So using attrs: { innerHTML: ... }
means <div innerHTML="..."></div>
which of course doesn't produce the expected result client side. innerHTML
is a property of DOM elements so it only has a meaning in props
.
A virtual dom is a way to represent any kind of HTML in a "javascript land" (i.e it's not an abstraction which allows to mix both HTML & virtual nodes to write templates). So if you have some HTML to render you will need to represent it using Tag
& Text
only (either manually or using an html parser). Btw, it's generaly a job for another libraries like JSX or similar. Personnaly I'm not coding with Tag
& Text
directly. I'm coding with regular HTML templates and I'm using an html parser at built time which convert all my HTML into a dom-layer
compatible syntax.
The other option is to put all static HTML outside the virtual dom representation and only using Tag
& Text
to represent dynamic HTML parts only. Anyhow you won't be able to use some innerHTML
property with virtual-dom
or Deku
and makes it work server side.
Note sure to understand what you mean by more restrictive. In Deku
for example it seems to be impossible to set some DOM element properties through ElementNode only attributes has been considered here. So if almost all can be done through attributes, it still some specific cases where properties are required. In virtual-dom
properties are the DOM element properties and properties.attributes
are the attributes. So it seems quite generic but what if you need to embed some more data in a virtual node ? Do we need to mix them up with classic DOM element properties ? or adding some other parameters like key
or namespace
, etc. ? In dom-layer
Tag take a config. So properties are in props
, attributes in attrs
, etc. and furthermore you can add any extra data you want to embed in either in data
or using a custom key.
Imo dom-layer
is a way more flexible than Deku
or virtual-dom
so I'm really curious to know what limitation you are facing on with dom-layer
you was able to acheive with Deku
or virtual-dom
@jails Limitation: I can't find a way to set innerHTML
on server-side using dom-layer
.
And from what I read, you are saying it's not possible in dom-layer
, at least not natively, that's fine, I just need a confirmation.
I use innerHTML a lot with virtual-dom
and deku
on server-side, so I have no idea why you believe they can't handle innerHTML property. But that's beside my point.
PS: by restrictive I mean the writing the hyperscript itself, look at my example https://gist.github.com/bitinn/ca83c32f041f89e4e5ad and you can see virtual-dom
and deku
are quite expressive in their use of hyperscript, I need not to worry about whether it's a Text node or a Tag node too much.
I'm not sure to understand. innerHTML
works the same way in dom-layer
, virtual-dom
& deku
https://jsfiddle.net/s5p3zfnh/. How are you using virtual-dom
& deku
with innerHTML
server-side since they don't support server side rendering out of the box ?
dom-layer
& virtual-dom
shares the same virtual nodes. Tag
=== VNode
and Text
=== VText
. There's no difference. And in the same way you can build a similar hyperscript function layer as virtual-dom do.
I'm using the following one, to speed up spec writing for example.
function h(context, children) {
var context = context || {};
var children = children || [];
if (typeof context === "string") {
return new Text(context);
}
var tagName = (context.tagName || "div").toLowerCase();
delete context.tagName;
return new Tag(tagName, context, children.map(function(value, key) {
if (typeof value === "string") {
return new Text(value);
}
return value;
}));
}
and you can use it like the following for example:
h({ tagName: "span" }, ["hello"]);
Both document.createElement()
&& document.createTextNode()
are required to build an HTML tree dynamically. So both Tag
&& Text
are required. However it's definitly possible to assume that string
values are Text
and abstract this assumption in an h()
hyperscript function.
Makes more sense ?
I worked on vdom-to-html
for virtual-dom
so maybe it's a good reference, it render hyperscript into plain html and we do handle innerHTML property on server-side (it's quite simple actually).
Oh ok, well I see no reason to not allow innerHTML
to be rendered as is if the node doesn't have any children defined, fixed in https://github.com/crysalead-js/dom-layer/commit/2bce87a0ed8b2a1ffb93b2f17ab418ba3bb9455a
If I read #14 correctly, everything will be escaped, if I want to introduce an element that takes static html content or something like inline javascript, I have to roll my own?