         else if type is 'text'
             tag.content
 
+    use: (checker) ->
+        @checkers.push checker
+
+    approve: (parent, tag, callback) ->
+        checkers = @checkers.slice()
+        next = (tag) ->
+            checker = checkers.shift() ? callback
+            checker parent, tag, next
+        next(tag)
+
 # exports
 
 module.exports = { Tag, Builder }

    opts = deep_merge @builder.opts, opts # possibility to overwrite existing opts, like pretty
    opts.builder = @builder

    @pending.push tag = new @builder.Tag name, attrs, null, opts
    tag.parent = this

    tag.on 'data', events.data = (data) =>
        if @pending[0] is tag
            @write data
        else
            @buffer.push data

    pipe = (event) =>
        tag.on event, events[event] = =>
            @emit event, arguments...
    pipe event for event in EVENTS

    tag.once 'end', on_end = =>
        if @pending[0] is tag
            if tag.pending.length
                tag.pending[0].once 'end', on_end
            else
                if tag.buffer.length
                    @buffer = @buffer.concat tag.buffer
                    tag.buffer = []
                @pending = @pending.slice(1)
                rmevents.call tag, events
                flush.call this
                if @closed and @pending.length is 0
                    @end()
        else
            for known, i in @pending
                if tag is known
                    @pending = @pending.slice(0,i).concat @pending.slice i+1
                    if @buffer.length
                        before = @pending[i-1]
                        before.buffer = before.buffer.concat @buffer
                        @buffer = []
                    rmevents.call tag, events
                    if @closed is 'pending'
                        flush.call this
                        @end()
                    return
            throw new Error("this shouldn't happen D:")
        return

    @emit 'new', tag
    @emit 'add', tag
    tag.children children, opts if children?
    return tag

sync_tag = ->
    [name, attrs, children, opts] = parse_args arguments...


class Builder extends EventEmitter
    constructor: (@opts = {}) ->
        # values
        @builder = this
        @buffer = [] # for child output
        @pending = [] # no open child tag
        @checkers = [] # all the middlewares that have to approve a new tag
        # states
        @closed = no
        # defaults
        @opts.pretty ?= off
        @level = @opts.level ? -1
        # api
        @Tag = Tag
        @tag = new_tag
        @$tag = sync_tag
