+ return if afe.length is 0
+ if afe[0].type is TYPE_MARKER or afe[0] in open_els
+ return
+ # Rewind
+ i = 0
+ loop
+ if i is afe.length - 1
+ break
+ i += 1
+ if afe[i].type is TYPE_MARKER or afe[i] in open_els
+ i -= 1 # Advance
+ break
+ # Create
+ loop
+ el = afe[i].shallow_clone()
+ tree_insert_tag el
+ afe[i] = el
+ break if i is 0
+ i -= 1
+
+ # http://www.w3.org/TR/html5/syntax.html#adoption-agency-algorithm
+ # adoption agency algorithm
+ adoption_agency = (subject) ->
+ if open_els[0].name is subject
+ el = open_els[0]
+ open_els.shift()
+ # remove it from the list of active formatting elements (if found)
+ for t, i in afe
+ if t is el
+ afe.splice i, 1
+ break
+ return
+ outer = 0
+ loop
+ if outer >= 8
+ return
+ outer += 1
+ fe = null
+ for t, fe_index in afe
+ if t.type is TYPE_MARKER
+ break
+ if t.name is subject
+ fe = t
+ break
+ if fe is null
+ in_body_any_other_end_tag subject
+ return
+ in_open_els = false
+ for t in open_els
+ if t is fe
+ in_open_els = true
+ break
+ unless in_open_els
+ parse_error()
+ # "remove it from the list" must mean afe, since it's not in open_els
+ afe.splice fe_index, 1
+ return
+ unless el_is_in_scope fe
+ parse_error()
+ return
+ unless open_els[0] is fe
+ parse_error()
+ # continue
+ fb = null
+ fb_index
+ for t, i in open_els
+ if t is fe
+ break
+ if el_is_special t
+ fb = t
+ fb_index = i
+ if fb is null
+ loop
+ t = open_els.shift()
+ if t is fe
+ afe.splice fe_index, 1
+ return
+ ca = open_els[fe_index + 1] # common ancestor
+ node_above = open_els[fb_index + 1] # next node if node isn't in open_els anymore
+ # 12. Let a bookmark note the position of formatting element in the list of active formatting elements relative to the elements on either side of it in the list.
+ bookmark = new_aaa_bookmark()
+ for t, i in afe
+ if t is fe
+ afe.splice i, 0, bookmark
+ node = last_node = fb
+ inner = 0
+ loop
+ inner += 1
+ node_next = null
+ for t, i in open_els
+ if t is node
+ node_next = open_els[i + 1]
+ break
+ node = node_next ? node_above
+ # TODO make sure node_above gets re-set if/when node is removed from open_els
+ if node is fe
+ break
+ node_in_afe = false
+ for t, i of afe
+ if t is node
+ if inner > 3
+ afe.splice i, 1
+ else
+ node_in_afe = true
+ break
+ unless node_in_afe
+ for t, i in open_els
+ if t is node
+ node_above = open_els[i + 1]
+ open_els.splice i, 1
+ break
+ continue
+ # 7. reate an element for the token for which the element node
+ # was created, in the HTML namespace, with common ancestor as
+ # the intended parent; replace the entry for node in the list
+ # of active formatting elements with an entry for the new
+ # element, replace the entry for node in the stack of open
+ # elements with an entry for the new element, and let node be
+ # the new element.
+ new_node = node.shallow_clone()
+ for t, i in afe
+ if t is node
+ afe[i] = new_node
+ break
+ for t, i in open_els
+ if t is node
+ open_els[i] = new_node
+ break
+ node = new_node
+ # 8. If last node is furthest block, then move the
+ # aforementioned bookmark to be immediately after the new node
+ # in the list of active formatting elements.
+ if last_node is fb
+ for t, i in afe
+ if t is bookmark
+ afe.splice i, 1
+ for t, i in afe
+ if t is node
+ # TODO test: position i gets you "after"?
+ afe.splice i, 0, new_aaa_bookmark()
+ # 9. Insert last node into node, first removing it from its
+ # previous parent node if any.
+ if last_node.parent?
+ for c, i of last_node.parent.children
+ if c is last_node
+ last_node.parent.children.splice i, 1
+ node.children.push last_node
+ last_node.parent = node
+ # 10. Let last node be node.
+ last_node = node
+ # 11. Return to the step labeled inner loop.
+ # 14. Insert whatever last node ended up being in the previous step
+ # at the appropriate place for inserting a node, but using common
+ # ancestor as the override target.
+ tree_insert_tag last_node, ca
+ # 15. Create an element for the token for which formatting element
+ # was created, in the HTML namespace, with furthest block as the
+ # intended parent.
+ new_element = fe.shallow_clone()
+ # 16. Take all of the child nodes of furthest block and append them
+ # to the element created in the last step.
+ while fb.children.length
+ t = fb.children.shift()
+ t.parent = new_element
+ new_element.children.push t
+ # 17. Append that new element to furthest block.
+ new_element.parent = fb
+ fb.children.push new_element
+ # 18. Remove formatting element from the list of active formatting
+ # elements, and insert the new element into the list of active
+ # formatting elements at the position of the aforementioned
+ # bookmark.
+ for t, i in afe
+ if t is fe
+ afe.splice i, 1
+ break
+ for t, i in afe
+ if t is bookmark
+ afe[i] = node
+ break
+ # 19. Remove formatting element from the stack of open elements,
+ # and insert the new element into the stack of open elements
+ # immediately below the position of furthest block in that stack.
+ for t, i of open_els
+ if t is fe
+ open_els.splice i, 1
+ break
+ for t, i of open_els
+ if t is fb
+ open_els.splice i, 0, new_element
+ break
+ # 20. Jump back to the step labeled outer loop.