I'm in the middle of writing a new template package in part to make this sort of thing easy. Once that's done and soaked, the existing package will be deprecated.
In the meantime, though, it shouldn't be too hard to do if you're willing to provide your own formatter map.
-rob
In case you're not too far along with the template language for
feature requests, autoescaping would be very easy to implement if I
can get a handle to the parse trees for a bundle of templates since
the easiest way to implement this is as a parse tree bundle to parse
tree bundle transformation. Having a whole compilation unit worth of
parse trees helps since I'm doing static analysis and being able to
look into callees where possible helps.
This is my first dive into Go, so I could I start by trying to get
some of the least possibly controversial bits written and conforming
with http://golang.org/doc/contribute.html and then send out a code
review request. Those early bits won't depend on the specifics of the
template language -- they depend on details of the HTML, JS, and CSS
grammars that make them attackable.
Or would it be better to first float a design document on this list
for criticism?
Sounds like a plausible plan, but let's discuss it first. Always good to do that. That'll help me in my universe too.
Not sure why a bundle is better than a tree. Or are you thinking about nested templates?
-rob
Perhaps "bundle" is the wrong word.
Many template languages have a way to include the output from one
template in another. If your new scheme does, then it would help to
be able to rewrite bother callers and callees at the same time to
handle cases like the below (apologies for the ad-hoc syntax). If
there is no call mechanism or one tree contains multiple template
definitions, then one tree works.
{template main}
<a {call foo} onclick="var {call foo}; alert(href)">
{/template}
{template bar}
href="{field1}"
{/template}
> -rob
-rob
They're private until you figure out what needs to be public. The plan was to keep things private and away from dependent fingers until we know what needs to be exported.
The idea is to write new packages, say template/html etc., that import the existing template and do something to the parse tree and perhaps execution engine, although I hope it's just the parse tree, which gets statically verified and slightly rewritten, perhaps by appending processors to the execution pipelines.
So I think we're on the same page.
-rob
Great. Then I'll work on exp/template/html and I'll send out a
monolithic change once I have it working that will include both
exp/template/html and changes to exp/template to make certain bits
public.
During the course of review, some of those public bits might be moved
back to private, and if/when it looks like exp/template/html is close
to ready I can split the monolithic change up as appropriate.
I may muck with the js and html predefined global functions used in pipelines.
Let's discuss this a little beforehand once you have some details worked out. (The word "monolithic" scares me.) I prefer to chat about the design before the code is written rather than through the codereview process.
-rob
> Let's discuss this a little beforehand once you have some details worked out. (The word "monolithic" scares me.) I prefer to chat about the design before the code is written rather than through the codereview process.
Fair enough. I sketched out a design earlier in this thread at
http://groups.google.com/group/golang-nuts/browse_thread/thread/e8bc7c771aae3f20/abdf127060ab7bf6?lnk=gst&q=autoescaping+order+of+work#abdf127060ab7bf6
I think I have a better handle on task 5 which relates to the parse
tree transformation.
I define a cascading inferences struct which contains
* a mapping from template name to template root
* a mapping from template name to the computed start context and end context
* a list of cloned templates
* a set of pipeline functions that need to be added to {{pipeline}}s
* possibly a list of warnings that might be displayed if this inferences turns
out to be part of the consistent view of the template set
Then I implement
func propagateContext(templates *Set, out *inferences)
which performs http://js-quasis-libraries-and-repl.googlecode.com/svn/trunk/safetemplate.html#context_propagation
and a function to apply the consistent *inferences to the *Set
The nodes all seem to have line numbers which is great, but I'm not
quite clear on how to get errors/warning messages back to the user or
whether panic is the most appropriate thing to do for errors and log
for warnings.
On that thread, you've broken up your intent into a number of
different tasks, but I think you're slicing the overall body of work
on the wrong axis.
For example, the first patch you proposed is at
http://codereview.appspot.com/4625052
This defines a zillion constants and states, and it's hard for me as a
reviewer to see the forest for the trees (even after I've read the
paper at http://js-quasis-libraries-and-repl.googlecode.com/svn/trunk/safetemplate.html).
For example, I'm not sure if "type State uint8" is the best
representation, but I can't tell without seeing how it'll be used. In
Go, we often represent a state machine state's by its transition
function, such as exp/template/lex.go's "type stateFn func(*lexer)
stateFn".
Instead, for a first patch, I would like to see something that's
end-to-end but with a simplified functionality. I'd pick just two
types of escaping (URL and HTML) and demonstrate that if my template
was:
`<form action="/foo/{{.Name}}/bar">Hello {{.Name}} etcetera`
then I could recognize the first action as a URL and the second as HTML PCDATA.
The URL-ness recognition doesn't have to be born perfect. Once we
agree on an overall design, we can check it in and iterate towards
covering all the CSS Double-Quoted URI corner cases.
If I have some time over the weekend, I might try this myself.
to facilitate that, it probably makes sense for me to do the work of breaking out the lexer and parser into subpackages of template that yours and other analyzers can use directly. how does that sound?
-rob
I can put together an end-to-end solution for a simplified HTML
grammar that ignores HTML comments, RCDATA and CDATA tags, that
naively assumes all templates start in a PCDATA context, and only
admits double quoted attributes and only tries to specially handle URI
attributes.
I don't think having the template lexer available would help.
To be more concrete, the proposal is that Rob will
take on the work to make the syntax tree available,
probably as types defined in a separate package,
the same way that exp/regexp has exp/regexp/syntax.
The idea is that the syntax tree is a decent way
to let higher-level packages analyze the templates.
Having done that, I think there's actually little at
the beginning that has to be designed. I'd be
happy with
package html // exp/template/html
func Analyze(*Set)
where Analyze just prints things it learns.
Getting to a point where that actually works
should be a whole bunch of small-step CLs during
which we can help you (Mike) pick up effective Go
idioms and you can help us understand the problem
domain better. By the time Analyze is printing the
right information everyone will be up to speed on
the two halves and we can figure out the right way
to use the analysis. It might be that we want to
give the new package the same API as template,
or it might be that we want to make it something you
ask for while using the real template.
The ideal progression would be a sequence of small
(~500 line, definitely not more than 1000 line) CLs,
so that we can do fine adjustments on the overall
trajectory in flight.
Russ
Understood. I will watch exp/template for any syntax checkins before
doing any further work.