Jeff Barczewski
2006-Aug-02 15:00 UTC
[Masterview-devel] simplified directive base - draft 3
How about something like this... I have most of this figured out how to code. I was thinking about adding optional hash to the event method so we could do stuff like event :stag, :render => :nothing when we want to eat the content. Also could be useful for other options I can instance_eval the block and that provides access to the instance variables like you would expect without having to prefix or pass in anything to block. I was thinking that the render method would take a ''position'' argument indicating whether to append this content to a stack which will be output before or after the middle (dcs.render) which will happen automatically unless indicated otherwise. Using the :render => :nothing option for a block we can easily suppress all output, but how to indicate that we want to suppress it when we want to render other things instead? It seems that when we are in a block, that the indication to prevent that would be done along near the other render commands. maybe using something like render :event, whatever to indicate we are influencing the output from dcs.render, if nil or maybe :nothing then omit, otherwise substitute the content provided. Also how to provide access to the dcs.render content, use a method called yield like rails? So var = yield gets the content and allows you to work with it before outputting if we use yield, then for consistency should our above render position be called render :yield (nil | :nothing | whatever replacement content) Not sure if :event or :yield is better, or whether there is a better term for this nested content? What do you think makes most sense? Are we getting closer? class MySpecialDirective < DirectiveBase attr_arg :obj, :quote => true attr_arg :method, :quote => true attr_arg :foo, { ''override with this value''} attr_arg :bar, { |x| x.downcase } # lowercasing the arg before setting it to @bar attr_arg :options, :merge => [:common_html, :size, :maxlength] event :stag do # outputs before, dcs.render(implied), and after content render :before ''something here'' render :before erb_content( ''text_area'', :obj, :method, :foo, :bar ) render :after erb_eval( attr[:class] ) end event :content, :render => :nothing # eat all the content, outputting nothing event :etag do # collects the dcs.render and manipulates before outputting con = yield con.gsub!( /foo/, ''bar'') render :event con end event :comment do # output the before, eat the dcs.render render :before ''hello'' render :event :nothing # or nil end end
Jeff Barczewski
2006-Aug-02 15:09 UTC
[Masterview-devel] simplified directive base - draft 3
well, trying out defining a method yield but it looks like we''d have to call it using self.yield unless I did something to remove the kernel one. Maybe it would be better to not use yield and come up with a different method name that represents the dcs.render (get serialized output for this event calling all nested directives). Let me know what you think. On 8/2/06, Jeff Barczewski <jeff.barczewski at gmail.com> wrote:> How about something like this... > > I have most of this figured out how to code. > > I was thinking about adding optional hash to the event method so we > could do stuff like > event :stag, :render => :nothing > when we want to eat the content. Also could be useful for other options > > I can instance_eval the block and that provides access to the instance > variables like you would expect without having to prefix or pass in > anything to block. > > I was thinking that the render method would take a ''position'' argument > indicating whether to append this content to a stack which will be > output before or after the middle (dcs.render) which will happen > automatically unless indicated otherwise. > > Using the :render => :nothing option for a block we can easily > suppress all output, but how to indicate that we want to suppress it > when we want to render other things instead? It seems that when we are > in a block, that the indication to prevent that would be done along > near the other render commands. > > maybe using something like > render :event, whatever > to indicate we are influencing the output from dcs.render, if nil or > maybe :nothing then omit, otherwise substitute the content provided. > > Also how to provide access to the dcs.render content, use a method > called yield like rails? > So var = yield gets the content and allows you to work with it before outputting > > if we use yield, then for consistency should our above render position be called > render :yield (nil | :nothing | whatever replacement content) > > Not sure if :event or :yield is better, or whether there is a better > term for this nested content? What do you think makes most sense? > > Are we getting closer? > > class MySpecialDirective < DirectiveBase > attr_arg :obj, :quote => true > attr_arg :method, :quote => true > attr_arg :foo, { ''override with this value''} > attr_arg :bar, { |x| x.downcase } # lowercasing the arg before setting it > to @bar > attr_arg :options, :merge => [:common_html, :size, :maxlength] > > event :stag do # outputs before, dcs.render(implied), and after content > render :before ''something here'' > render :before erb_content( ''text_area'', :obj, :method, :foo, :bar ) > render :after erb_eval( attr[:class] ) > end > > event :content, :render => :nothing # eat all the content, outputting nothing > > event :etag do # collects the dcs.render and manipulates before outputting > con = yield > con.gsub!( /foo/, ''bar'') > render :event con > end > > event :comment do # output the before, eat the dcs.render > render :before ''hello'' > render :event :nothing # or nil > end > > end >
I really hate the choice of "yield" in ruby, so I''m *fine* with a different name! ("yield" and the "rescue" exception terminology are my two real dislikes about ruby; neither of those terms relate to any of the ways I normally talk/think about block evaluation and exception handling) Some other reactions (opinions tempered by not having actually played with sketching this out in some real impl''s, which always leads to better instinct about what seems right): o I think I may actually *prefer* to declare the event''s block arg rather than having it instance_eval''d. Not sure I *want* my directive to have inst var access - it''s got its own inst vars and I think I prefer to think of it as having a distinct interface to the template-processor that''s using it, as opposed to being part of that guy. It makes the notation w/in an stag/etag handler less declarative, but I think that''s actually ok. The declarative aspect is nicely done by the new scheme we''re settling on for declaring intent about the attribute value encoding (attr_arg guys). But writing the processing part seems more like writing an action method in a controller or adding some behavior to a model, where some of what I say in the class implementation fits nicely into a declarative structure but then the part that''s actually about *doing* something really is more procedural and thus more like writing "normal code". Then the challenge is to have clean, simple protocol for things you want to access or generate. o I like render as the term to use for the operation which produces an effect on the output document. o render :before/:after are ok, but :event is funky. Maybe an alternative way to come at this is to think about this as hooking the processing events and shift the before/after notion to the handlers; then all you ever do w/in a handler is render (position is now implicit and doesn''t need to be specified). e.g., instead of your example event :stag do # outputs before, dcs.render(implied), and after content render :before ''something here'' render :before erb_content( ''text_area'', :obj, :method, :foo, :bar ) render :after erb_eval( attr[:class] ) end we might have: event :before_stag do # :before positioning of the emitted rendering is implied by when render ''something here'' render erb_content( ''text_area'', :obj, :method, :foo, :bar ) end ~ Deb -----Original Message----- From: Jeff Barczewski [mailto:jeff.barczewski at gmail.com] Sent: Wednesday, August 02, 2006 8:10 AM To: djlewis at acm.org; masterview-devel at rubyforge.org Subject: Re: simplified directive base - draft 3 well, trying out defining a method yield but it looks like we''d have to call it using self.yield unless I did something to remove the kernel one. Maybe it would be better to not use yield and come up with a different method name that represents the dcs.render (get serialized output for this event calling all nested directives). Let me know what you think.
Jeff Barczewski
2006-Aug-02 19:11 UTC
[Masterview-devel] simplified directive base - draft 3
Great! I was thinking along the same lines about the before after stuff, I''ll take a look at whether most of the attributes do one or the other or a combination. If they stick to one or the other then it makes sense to indicate the position as part of the event, but if they tend to do both then it might get hairy having to go here for that and there for something else. But let me check maybe the directives typically only do one type. As for the instance_eval, I was sort of thinking along those lines, but then I realized that we would be declaring this in a class and it is very close to a method (it is a dedicated block which is wrapped by some other processing). Sort of like you were saying this part is procedural and needs direct access to things, I think we''d want the block to have access to instance variables giving the ability to create new ones etc, because these will be the way that you communicate across the object from one method to another. For instance you might start something in the start tag and then be completing it in the end tag or working on the content or nested tags. Instance variables will keep your state between these events, so need easy way to get at and create them. Seems like if we used a non-instance eval approach that we''d lose some of this freedom (you''d need accessors and would need a way to create new instance vars) and everything that wasn''t a class method would need a prefix in front (e.). Seems to me that working in that mode would be more confusing. I think I''d rather be in the instance mode like a normal method call and then do something different to call class methods. You mentioned the block having its own instance vars, but not sure what you meant. It can certainly have local variables, but since it is only a block it wouldn''t have instance vars and even if it did they would go away when the block completes, right? Given all this, it seems to make sense to use an instance_eval approach giving us easy access to all instance vars, simplified syntax, elimate the need for the block var decl |x|, feels just like a regular instance method. I still need to define a way to read/eat the event output. Let me take these ideas you presented and see how they would look using some real examples, and maybe the best approach will pop out. Thanks for the feedback. Let me know if I am still missing something regarding the instance_eval discussion.
ah, maybe we have a disconnect in how we''re each thinking about this that''s leading to diff notions of blocks and evals and inst vars [terminology: I''m going to talk about "template processor" to stay out of parser/dcs etc details and keep this a bit more abstract] I''m still thinking of a directive implementation as a class, with life cycle: instantiated when template processor processes an element start tag in the source template document. Constructed with the string value of the directive attribute provided (dirProcessor SomeDirective.new(attr_value)...), with our new parser-aids hooked up to initialize its inst vars from the declarative notation in the class decl that essentially give us the signature - some number of essentially positional args, possibly with defaults, plus optionally has collected for trailing option specs. Template processor is responsible for hanging onto the directive handlers for an element and invoking them at appropriate points during the element processing (stag, etag). Directive processor instance is thrown away when the element is completed. [maybe the template processor itself is also an arg to the directive handler constructor, along with the attribute value - then maybe the block/event-method arg does indeed go away] So that''s why I think of the directive guy as having its own state, derived from the attribute value string, and that this is separate from the overall state of the template processing. It gets initialized at the start tag, it can keep whatever it wants, and it''s separate from any other directives on that element or other elements in the template. And having sketched out that story, here''s another possible wrinkle: we''re thinking about ''attr_arg'' sort of declarative notation to express the expected signature of the attribute value for this directive. Maybe then there''s also a declarative notation which expresses which events it wants to be invoked on and the method to call for each event. Similar to before/after filters on controller actions. Maybe that''s the way to the declarative DSL notation for common things, with ability to drop into a method for anything that''s really procedural or complicated. ~ Deb
Jeff Barczewski
2006-Aug-03 12:38 UTC
[Masterview-devel] simplified directive base - draft 3
Right, I don''t think we are too far off in our thoughts. I agree with pretty much what you said, though I would just add a few points. Template processor finds all the directives that are declared in attributes as well as any that are set to auto run (like our inline erb expansion one which allows inline substitution). Then after having that list it goes through and finds out which directives respond to the event it is getting ready to process, it also checks if the directives respond to child_tag_event or descendent_tag_event, as well as wildcarded options child_any_event, descendent_any_event based on the nesting etc (this allows directives to fire when child events are hit). Anyway once it finds directives that respond to any of these it creates a call stack and sorts based on priority and nesting depth, then it proceeds to instantiate and call these. Each directive gets the attr_value as well as access to the attributes and other content. It can create instance variables that will persist between events so that some state can be set in start element and then utilized in end element. Each directive processes the events such that they work like an interceptor, pipeline, or filter where each can affect the input and outcome of each other also choosing whether any further processing occurs on this event. I don''t want to change any of the main parser mechanisms right now (other than your multi-namespace enhancement), I am only wanting to simplify the directive class api to make it easier to build these. I still think the main process is sound and accomodates everything we need, just want to simplify building these classes. So the directive DSL we have been discussing is involved in creating the directive classes. We tell the directive how it can parse its attr_value (if necessary), and we respond to events affecting input and outcome. So the attr_arg methods tell the class how to parse its attr_value and the rest is how to process or how to create these event methods and what happens in them. Using a instance_eval block dsl we can simplify and encapsulate some of the necessary processing namely preparing the argument objects initially, calling next interceptor in the chain, and handling post processing to wrap up what gets returned up to next interceptor (and eventually serialized). So this DSL we are describing is used inside the directive class itself for the above purposes. The blocks are all part of what needs to happen in each event call. So yes, if we have a event :before_stag then I will build a instance method called stag and inside of it this block will be invoked at the proper time. If we had an event :stag or a event :after_stag these would also be invoked in that same stag instance method. So I would end up creating one stag method that potentially invokes three blocks (if they exist). Each of these blocks is a sub instance method so that''s why I think they need instance_eval access so they can intuitively access everything about the directive instance (vars, methods) without grief. Developers can consider themselves writing actual instance methods with the syntax except that we are doing a little pre an post processing and combining around all this.>From our discussions, the syntax that feels the best so far (thinkingabout what current and future directives do) is this: class MySpecialDirective < DirectiveBase attr_arg :obj, :quote => true attr_arg :method, :quote => true attr_arg :foo, { ''override with this value''} attr_arg :bar, { |x| x.downcase } # lowercasing the arg before setting it to @bar attr_arg :options, :merge => [:common_html, :size, :maxlength] event :before_stag do # outputs this before any stag output render erb_eval( ''if'' attr[:class] ) end event :stag do # outputs this instead of what would be output for stag render erb_content( ''text_area'', :obj, :method, :foo, :bar ) # if they hadn''t called render here, then the normal output for stag # would still automatically be created, they could have also # called render :nothing if they wanted to suppress or conditionally # suppress. end event :content, :render => :nothing # eat all the content, outputting nothing # if we hadn''t put this here then the directive would not have even been called # for a content event, but we acutlly want to be called and we are stopping # any output. event :etag do # collects the dcs.render and manipulates before outputting con = event_result() # get the output that would be rendered con.gsub!( /foo/, ''bar'') render :event con # render this modified output instead end event :after_child_td_stag # render something after a child td start tag render ''something after child td tag'' end end The above ends up creating a directive class with the following instance methods stag content etag child_td_stag and all the necesary infrastructure to store and call these other blocks at the right time. I like how putting the position into the pseudo event allows us to clean up things and it provides a way to override or simply allow content to be rendered without developer forgetting to call dcs.render (they specifically say when they want to render nothing or to replace the output). It also prevents then from having to build up an array of output to return, this is wrapped up by our render methods. As for getting the output from the other interceptors (directives and serializer), do you like the name event_result() for this method call which will be used whenever you want to get the output and manipulate it?? This is instead of yield and continue ideas we had earlier. It basically allows processing to continue by calling dcs.render and returns that result. How does this feel to you? I think we are getting close. Thanks for your continued input!! Jeff
Jeff Barczewski
2006-Aug-03 12:42 UTC
[Masterview-devel] simplified directive base - draft 3
One typo in my previous post> event :etag do # collects the dcs.render and manipulates before outputting > con = event_result() # get the output that would be rendered > con.gsub!( /foo/, ''bar'') > render :event con # render this modified output instead > end >should be event :etag do # collects the dcs.render and manipulates before outputting con = event_result() # get the output that would be rendered con.gsub!( /foo/, ''bar'') render con # render this modified output instead end we do not need positioning since that is implied in the pseudo event name. On 8/3/06, Jeff Barczewski <jeff.barczewski at gmail.com> wrote:> Right, I don''t think we are too far off in our thoughts. > > I agree with pretty much what you said, though I would just add a few > points. Template processor finds all the directives that are declared > in attributes as well as any that are set to auto run (like our inline > erb expansion one which allows inline substitution). Then after having > that list it goes through and finds out which directives respond to > the event it is getting ready to process, it also checks if the > directives respond to child_tag_event or descendent_tag_event, as well > as wildcarded options child_any_event, descendent_any_event based on > the nesting etc (this allows directives to fire when child events are > hit). Anyway once it finds directives that respond to any of these it > creates a call stack and sorts based on priority and nesting depth, > then it proceeds to instantiate and call these. > > Each directive gets the attr_value as well as access to the attributes > and other content. It can create instance variables that will persist > between events so that some state can be set in start element and then > utilized in end element. > > Each directive processes the events such that they work like an > interceptor, pipeline, or filter where each can affect the input and > outcome of each other also choosing whether any further processing > occurs on this event. > > I don''t want to change any of the main parser mechanisms right now > (other than your multi-namespace enhancement), I am only wanting to > simplify the directive class api to make it easier to build these. I > still think the main process is sound and accomodates everything we > need, just want to simplify building these classes. > > So the directive DSL we have been discussing is involved in creating > the directive classes. We tell the directive how it can parse its > attr_value (if necessary), and we respond to events affecting input > and outcome. So the attr_arg methods tell the class how to parse its > attr_value and the rest is how to process or how to create these event > methods and what happens in them. > > Using a instance_eval block dsl we can simplify and encapsulate some > of the necessary processing namely preparing the argument objects > initially, calling next interceptor in the chain, and handling post > processing to wrap up what gets returned up to next interceptor (and > eventually serialized). > > So this DSL we are describing is used inside the directive class > itself for the above purposes. The blocks are all part of what needs > to happen in each event call. So yes, if we have a > > event :before_stag > > then I will build a instance method called stag and inside of it this > block will be invoked at the proper time. > > If we had an > > event :stag > or a > event :after_stag > > these would also be invoked in that same stag instance method. So I > would end up creating one stag method that potentially invokes three > blocks (if they exist). Each of these blocks is a sub instance method > so that''s why I think they need instance_eval access so they can > intuitively access everything about the directive instance (vars, > methods) without grief. Developers can consider themselves writing > actual instance methods with the syntax except that we are doing a > little pre an post processing and combining around all this. > > From our discussions, the syntax that feels the best so far (thinking > about what current and future directives do) is this: > > class MySpecialDirective < DirectiveBase > attr_arg :obj, :quote => true > attr_arg :method, :quote => true > attr_arg :foo, { ''override with this value''} > attr_arg :bar, { |x| x.downcase } # lowercasing the arg before setting it > to @bar > attr_arg :options, :merge => [:common_html, :size, :maxlength] > > event :before_stag do # outputs this before any stag output > render erb_eval( ''if'' attr[:class] ) > end > > event :stag do # outputs this instead of what would be output for stag > render erb_content( ''text_area'', :obj, :method, :foo, :bar ) > # if they hadn''t called render here, then the normal output for stag > # would still automatically be created, they could have also > # called render :nothing if they wanted to suppress or conditionally > # suppress. > end > > event :content, :render => :nothing # eat all the content, outputting nothing > # if we hadn''t put this here then the directive would not have even been called > # for a content event, but we acutlly want to be called and we are stopping > # any output. > > event :etag do # collects the dcs.render and manipulates before outputting > con = event_result() # get the output that would be rendered > con.gsub!( /foo/, ''bar'') > render :event con # render this modified output instead > end > > event :after_child_td_stag # render something after a child td start tag > render ''something after child td tag'' > end > > end > > > The above ends up creating a directive class with the following instance methods > stag > content > etag > child_td_stag > > and all the necesary infrastructure to store and call these other > blocks at the right time. > > > > I like how putting the position into the pseudo event allows us to > clean up things and it provides a way to override or simply allow > content to be rendered without developer forgetting to call dcs.render > (they specifically say when they want to render nothing or to replace > the output). It also prevents then from having to build up an array of > output to return, this is wrapped up by our render methods. > > As for getting the output from the other interceptors (directives and > serializer), do you like the name event_result() for this method call > which will be used whenever you want to get the output and manipulate > it?? This is instead of yield and continue ideas we had earlier. It > basically allows processing to continue by calling dcs.render and > returns that result. > > How does this feel to you? > > I think we are getting close. Thanks for your continued input!! > > Jeff >
Jeff Barczewski
2006-Aug-03 14:57 UTC
[Masterview-devel] simplified directive base - draft 3
Terminology: ''event'' in the context of this discussion are places that one can hook into the rendering process like :before_stag, :stag, :after_stag. These are different (more granular) than the rexml events (stag, etag, ...). They are not actual directive class instance methods, but they are related in that many of these events will be fired under each actual dynamically created instance method. After looking through the existing directives I think the events will work well however we may want to consider a few additional ones to make things easier and make more sense. content - allow straight forward place to override content between start tag and end tag (this is much more useful then the rexml characters event since this will be the accumulated content including all nested tags, comments, etc) tag - allow straight forward way to replace entire tag and all enclosing content, very common usage for many directives that replace all (form helpers). Otherwise they have to capture stag, capture content, and etag. Since this is such a common usage and people could forget to do a step, having a event like this will allow them to easily get the results they expect. Simply render whatever they want to replace everything with. Under the covers this event wraps up stag, after_stag, content, before_etag, etag. One could still also handle :before_stag and :after_etag to add additional wrapper content if necessary but the others will all be accounted for. So our pseudo event structure will be something this: In the order things are called with the number of calls in parens before_stag (1) stag (1) after_stag characters (0..many) comment (0..many) .... nested tags and events ... (0..many) content (1) - rolls up all (characters, comments, nested) - should it include after_stag and before_etag? I can see arguments for both ways. before_etag (1) etag (1) tag (1) - rolls up everything between stag and etag after_etag(1) Event though this looks large in actuallity the code for most directives will only need to hook one or two of these, so what is complex here, simplifies what is done in the directives. Is ''tag'' a good name for the event that encapsulates stag to etag data? Should content event exclude after_stag and before_etag or include it? And from previous message so it doesn''t get lost is ''event_result()'' a good name for the method which allows you to get access to what the event would be rendering (allowing you to modify it before pushing out)? Are things coming together in your mind? I think they are for me and I think the resulting directive code looks like it gets simpler with each iteration we have been doing (which hopefully means we are going in the right direction). I just want to get the terminology and names for things as clear as possible to make it easy for new users to grasp and understand. The easier it is, then the less questions we''ll get. Thanks, Jeff
Jeff - ok, I think this is starting to settle into a pretty nice shape. RE: what to call the message for getting at the output (event_result() vs. yield and continue ideas we had earlier) event_result() seems a bit odd to me. maybe something along the lines of render_result() or output_content() - want to convey the sense "I''d like the current result of the output from rendering at this point" ~ Deb
content rather than rexml''s more detailed characters and comments: yes - logically I just want the element content all/most of the time. I wouldn''t even worry about exposing those more detailed events in our directive processing model until there''s a justification; can always add later if needed. [can''t think offhand why I care about comments, unless someone was using them to embed processing directives via comment annotation conventions] Rather than ''tag'', suggest ''element'' per the terminology of the DOM model. An element consists of (optional) text content wrapped in start/end tags; may have child elements; may have attributes. So now we have an easy to hook into either the element''s content or the entire element, as well as fiddling attributes on the element''s (start) tag via the stag event, and I think that captures most of what a directive is likely to be interested in. So the directive processing event structure could be simplified a bit to: before_stag (1) stag (1) after_stag (1) ...nested element events (0 or more) content (0 or 1 - this is just the immediate content, *not* child elements) before_etag (1) etag(1) element (1) - rolls up everything between stag and etag after_etag(1) This looks pretty good, I think it''s about right now. BTW it''s the nature of this sort of design that it takes at least of few iterations. Every time you do a version, things get clearer and as you get closer to goodness possibilities appear that you couldn''t see earlier because the model was too cluttered or too far away from a clean way of characterizing what''s going on. ~ Deb
Jeff Barczewski
2006-Aug-03 18:50 UTC
[Masterview-devel] Fwd: simplified directive base - draft 3
copy for the archive. ---------- Forwarded message ---------- From: Jeff Barczewski <jeff.barczewski at gmail.com> Date: Aug 3, 2006 1:32 PM Subject: Re: simplified directive base - draft 3 To: djlewis at acm.org render_result() seems to convey the proper meaning element is fine with me. Yes, comments could be used for embedded processing directives. We aren''t currently doing this but there are legitimate cases for this. The content method currently accesses everything in between the since you either are wanting to clear it all, read it including anything that was substituted in from other tags, use it in your processing, or modify the resultant output. Also I don''t have any way to only get the non nested tag content, everything rolls up at each level, by the time I get everything there is no distinction between direct text content and output from nested tags. In all the use cases I have currently and the ones on the drawing board this works well since, we always want all the content, for instance when doing a mv:content="hello" we are wanting to wipe out everything inside because it is likely to be sample data. I can however leave the after_stag and before_etag in or out of the content event. Not sure which makes more sense. I don''t know that the current directives care much either way. I guess excluding it makes the most sense your primarily talking about the children here not what we just got through adding in. I think everything else is looking pretty good. I''ll see how the directives will look with the new syntax, I think it will be a work of art :-) crunching a lot of busy fragile code down to just a few lines of fairly declartive robust code. Thanks for your help in this! Jeff On 8/3/06, Deb Lewis <djlewis at acm.org> wrote:> content rather than rexml''s more detailed characters and comments: yes - > logically I just want the element content all/most of the time. I wouldn''t > even worry about exposing those more detailed events in our directive > processing model until there''s a justification; can always add later if > needed. > > [can''t think offhand why I care about comments, unless someone was using > them to embed processing directives via comment annotation conventions] > > Rather than ''tag'', suggest ''element'' per the terminology of the DOM model. > An element consists of (optional) text content wrapped in start/end tags; > may have child elements; may have attributes. > > So now we have an easy to hook into either the element''s content or the > entire element, as well as fiddling attributes on the element''s (start) tag > via the stag event, and I think that captures most of what a directive is > likely to be interested in. > > So the directive processing event structure could be simplified a bit to: > > before_stag (1) > stag (1) > after_stag (1) > ...nested element events (0 or more) > content (0 or 1 - this is just the immediate content, *not* child > elements) > before_etag (1) > etag(1) > element (1) - rolls up everything between stag and etag > after_etag(1) > > This looks pretty good, I think it''s about right now. BTW it''s the nature > of this sort of design that it takes at least of few iterations. Every time > you do a version, things get clearer and as you get closer to goodness > possibilities appear that you couldn''t see earlier because the model was too > cluttered or too far away from a clean way of characterizing what''s going > on. > > ~ Deb > >