         tag.builder ?= @builder
         tag.parent  ?= this
 
-        self = this
-        listeners = {}
-        pipe = (event) ->
-            tag.on? event, listeners[event] = ->
-                self.emit event, arguments...
-        dispose = (el) ->
-            return unless el is self or el is tag
-            self.removeListener('repipe', repipe)
-            self.removeListener('remove', dispose)
-            tag.removeListener?('remove', dispose)
-            for event in EVENTS
-                if (listener = listeners[event])?
-                    tag.removeListener?(event, listener)
-            listeners = {}
-        wire = ->
-            pipe event for event in EVENTS
-            tag.once?('remove', dispose)
-            self.once('remove', dispose)
-            self.once('repipe', repipe)
-        repipe = (replacement) ->
-            dispose(self)
-            self = replacement
-            wire()
-        # enough preparation, lets do it:
-        wire()
+        connect_tags(this, tag)
 
         @emit 'add', this, tag
         @emit 'new', tag

    return [name, attrs, children, opts]


add_tag = (newtag, callback) ->
    return callback?.call(this) unless newtag?
    # only when the builder approves the new tag we can proceed with announcing

    replace: (rawtag) =>
        tag = @builder?.query 'tag', this, rawtag
        tag = rawtag unless tag? or @builder?
        return this if this is tag
        @emit 'replace', this, tag
        tag.parent  ?= @parent
        tag.builder ?= @builder
        if @builder is tag.builder
            @builder = null
        @parent = null
        @emit 'replaced', tag # internal
        tag

    remove: () =>
        @closed = 'removed' unless @closed
        @emit 'remove', this
        @emit 'removed' # internal
        @removeAllListeners()
        this

