<HTML><BODY style="word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space; "><BR><DIV><DIV>On Jun 2, 2005, at 11:18 PM, Ian Bicking wrote:</DIV><BR class="Apple-interchange-newline"><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">While we're on the topic of DOM-based templating...</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">FormEncode has a module htmlfill<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">(<A href="http://formencode.org/docs/htmlfill.html">http://formencode.org/docs/htmlfill.html</A>), which is basically like<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">DOM-based templating that just knows about HTML forms.<SPAN class="Apple-converted-space">  </SPAN>But currently it<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">doesn't use a DOM, it uses an HTMLParser subclass.<SPAN class="Apple-converted-space">  </SPAN>This makes it much<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">more complex than it would otherwise be, and misses out on some<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">potential performance gains -- many times the input to htmlfill will be<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">output from a template or HTML generator, and so often the DOM from the<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">template is serialized to text, then parsed again.</DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><BR></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">I had thought about moving this to a DOM or DOM-ish thing of some sort,<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">but I don't know which one.<SPAN class="Apple-converted-space">  </SPAN>Unfortunately many of the options are not<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">very humane -- that is, they are "correct", but not user-friendly.<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">Here's what I'd like, and maybe someone can suggest something (I won't<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">claim HTMLParser is that humane either; but I'm looking to improve<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">this).<SPAN class="Apple-converted-space">  </SPAN>Here's what I'd like:</DIV></BLOCKQUOTE><DIV><BR class="khtml-block-placeholder"></DIV><DIV>We've talked about this slightly before, but I think now more than ever stan can be that DOM. I don't think it would be too much work; it would mostly require removing assumptions that other nevow modules are available. I think stan could be broken out of nevow and into a standalone thing by pulling these modules:</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>nevow.stan</DIV><DIV>nevow.tags</DIV><DIV>nevow.loaders</DIV><DIV>nevow.context</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>And the package:</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>nevow.flat</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>I'm willing to do the work, and I'm willing to remove assumptions it makes and refactor things until they are clean. The module which would require the most work is nevow.context -- an internal rendering implementation detail that Nevow makes explicit but I would want to hide from non-Nevow users of stan. nevow.context was the first module of nevow to be written, and has a bunch of crufty bad decisions that haven't yet been refactored out of existence. But I'd like to do it, and this would give me an excuse to.</DIV><BR><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">* Can parse HTML, not just XHTML.<SPAN class="Apple-converted-space">  </SPAN>Not the crazy HTML browsers parse,<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">but unambiguous well-formed HTML.<SPAN class="Apple-converted-space">  </SPAN>I don't like the idea of putting the<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">HTML through tidy; that's fine for a screen-scraper, but is way too<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">defensive for this kind of thing.</DIV></BLOCKQUOTE><DIV><BR class="khtml-block-placeholder"></DIV><DIV>nevow.loaders.htmlfile does a good job of parsing normal html. nevow.loaders.xmlfile parses strict XHTML and allows more tag tricks, but I think casual users won't notice the difference, especially for the purpose you desire.</DIV><BR><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">* Can generate HTML.<SPAN class="Apple-converted-space">  </SPAN>This is probably easy to tack onto most systems,<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">even if it isn't present now -- it's just a couple rules about how to<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">serialize tags.</DIV></BLOCKQUOTE><DIV><BR class="khtml-block-placeholder"></DIV><DIV>HTML rather than XHTML? I'm curious what the motivation for this is, and if you know what the couple of rules would be. I think it wouldn't be too hard.</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>Hmm, I guess the motivation for the previous point is the next point?</DIV><BR><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">* Doesn't modify the output at all for areas where no transformations<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">occurred.<SPAN class="Apple-converted-space">  </SPAN>It doesn't wipe out whitespace.<SPAN class="Apple-converted-space">  </SPAN>It *definitely* doesn't lose<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">comments.<SPAN class="Apple-converted-space">  </SPAN>It keeps attribute order.<SPAN class="Apple-converted-space">  </SPAN>When nodes are modified it's<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">sometimes ambiguous how that effects the output, so if attribute order<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">is lost there it's not that big a deal.</DIV></BLOCKQUOTE><DIV><BR class="khtml-block-placeholder"></DIV><DIV>stan is whitespace in, whitespace out. It keeps comments. It uses a dict for attributes, but this could be changed easily. nevow.url uses a list of tuples, because order is actually important there. This means it needs to have a different API; it has .add() as well as .replace(). Add adds a new key value pair, even if the key is already present; replace finds any existing keys and puts a new value in it's place, preserving the original order.</DIV><BR><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">* Can output nicely-formatted code.<SPAN class="Apple-converted-space">  </SPAN>Probably easy to add, but nice if<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">it's already there.<SPAN class="Apple-converted-space">  </SPAN>This is, of course, entirely contrary to the<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">previous item ;)<SPAN class="Apple-converted-space">  </SPAN>When generating nodes *purely* from Python, systems<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">tend to produce HTML/XML with no extra whitespace at all, and completely<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><SPAN class="Apple-converted-space">  </SPAN>unreadable.</DIV></BLOCKQUOTE><DIV><BR class="khtml-block-placeholder"></DIV><DIV>This is really, really, really a bad idea. While browsers claim to be whitespace agnostic, they make a huge rendering distinction between "no whitespace present" and "any whitespace present". Nevow preserves any whitespace that was originally in your template, but when generating tags from Python it can't, so it doesn't.</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>That said, it is something I have considered writing before. Woven had it. I found it to be more trouble than it is worth. I think it should be added, but you should have to go out of your way to turn it on, and it should be off by default.</DIV><BR><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">* Keeps around enough information to produce good error messages.<SPAN class="Apple-converted-space">  </SPAN>It<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">needs to be possible to figure out the line and maybe column where a<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">node was originally defined.<SPAN class="Apple-converted-space">  </SPAN>If we're supporting multiple<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">transformations by multiple systems, then this information needs to<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">persist through the transformations.<SPAN class="Apple-converted-space">  </SPAN>I think this is a really important<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">and undervalued feature; anyone can write a templating system with<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">crappy error messages (and lots and lots of people do).<SPAN class="Apple-converted-space">  </SPAN>Good error<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">messages set a templating system apart.</DIV></BLOCKQUOTE><DIV><BR class="khtml-block-placeholder"></DIV><DIV>A great idea. It would be trivial to add file/line/column information and populate it differently in each of the loaders. I love it, I'm going to go do it right now.</DIV><BR><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">* Reasonably fast.</DIV></BLOCKQUOTE><DIV><BR class="khtml-block-placeholder"></DIV><DIV>Nevow was designed as an optimization of woven, and as a result is pretty fast. It has a two-pass system where one pass is taken when the template is initially loaded (once per template per process, assuming the template doesn't change on disk) and non-important nodes are optimized out of what actually happens at render time.</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>There's also a bunch of low hanging optimization work in nevow.context. When I originally wrote it, I was worried about people mutating things so I made lots of copies. In the meantime, it turns out that the "correct" style of using it is to not mutate things but be somewhat functional and side effect free. Since mutating is still nice for some things, the objects which get mutated get copied before you get called to mutate them. But, a lot, lot more copying currently happens than is necessary.</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>Yet another thing I have been meaning to do but haven't gotten around to, that this might encourage me to do.</DIV><BR><BLOCKQUOTE type="cite"><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">I've played around just a bit with ElementTree, but I only felt so-so<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">about it.<SPAN class="Apple-converted-space">  </SPAN>I felt like it was pretty correct, but not very humane --<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">maybe that'd be good enough if I was processing big XML documents, but<SPAN class="Apple-converted-space"> </SPAN></DIV><DIV style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">it doesn't work for HTML templating.</DIV></BLOCKQUOTE><BR></DIV><DIV>Agreed.</DIV><DIV><BR class="khtml-block-placeholder"></DIV><DIV>dp</DIV><DIV><BR class="khtml-block-placeholder"></DIV><FONT class="Apple-style-span" color="#0000DD"></FONT></BODY></HTML>