anchor.diff:          )
           |> Array.concat
   
  -    let parseNodeAndSiblingsAsTemplate fileId (node: HtmlNode) =
  +    let parseNodeChildrenAsTemplate fileId (parentNode: HtmlNode) =
           let state = ParseState(fileId)
           let src =
               use s = new StringWriter()
               let rec l = function
                   | null -> s.ToString()
                   | (n : HtmlNode) -> n.WriteTo s; l n.NextSibling
  -            l node
  -        let line, col =
  -            match node with
  -            | null -> 0, 0
  -            | node -> node.ParentNode.Line, node.ParentNode.LinePosition
  -        let value = parseNodeAndSiblings false state node
  +            l parentNode.FirstChild
  +        let line, col = parentNode.Line, parentNode.LinePosition
  +        let value = parseNodeAndSiblings false state parentNode.FirstChild
           { Holes = state.Holes; Value = value; Src = src; References = state.References
             SpecialHoles = state.SpecialHoles
             Line = line; Column = col }
  
positive.code:                     addHole attr.Value (holeDef HoleKind.ElemHandler)
                      yield Attr.OnAfterRender attr.Value
                  | VarAttr | HoleAttr | ReplaceAttr | TemplateAttr | ChildrenTemplateAttr ->
                      () // These are handled separately in parseNode*
                  | s when s.StartsWith EventAttrPrefix ->
                      let eventName = s.[EventAttrPrefix.Length..]
                      let eventType = getEventType eventName
  
negative.code:             n.Attributes.Add(attrName, a)
              res
  
      /// Detach a ws-template node from its parent.
      /// If it had a ws-replace attr, leave a dummy instead.
      /// Return it wrapped in a dummy parent.
      let detachTemplateNode (n: HtmlNode) =
          let doc = n.OwnerDocument
          match n.Attributes.[ReplaceAttr] with
          | null ->
              n.Remove()
          | a ->
              let repl = doc.CreateElement("div")
              repl.SetAttributeValue(ReplaceAttr, a.Value) |> ignore
              n.ParentNode.ReplaceChild(repl, n) |> ignore
              n.Attributes.Remove(ReplaceAttr)
          n.Attributes.Remove(TemplateAttr)
          let fakeroot = doc.CreateElement("div")
          fakeroot.AppendChild(n) |> ignore
          fakeroot
  
      /// Detach the contents of a ws-children-template node from their parent.
      /// Returns them in a new artificial parent.
      let detachChildrenTemplateNode (n: HtmlNode) =
          let repl = n.OwnerDocument.CreateElement(n.Name)
          for a in n.Attributes do
              if a.Name <> ChildrenTemplateAttr then
                  repl.Attributes.Add(a)
          n.ParentNode.ReplaceChild(repl, n) |> ignore
          n.Attributes.RemoveAll()
          n
  
      /// Find all the ws-template nodes, detach them and populate wsTemplates.
      let detachAllTemplateNodes (nodes: HtmlNode[]) (wsTemplates: Dictionary<WrappedTemplateName, HtmlNode>) =
          for n in nodes do
              let templateName = n.GetAttributeValue(TemplateAttr, "")
              let w = WrappedTemplateName(templateName)
              if wsTemplates.ContainsKey w then
                  failwithf "Template defined multiple times: %s" templateName
              wsTemplates.Add(w, detachTemplateNode n)
  
      /// Find all the ws-children-template nodes, detach them and populate wsTemplates.
      let detachAllChildrenTemplateNodes (nodes: HtmlNode[]) (wsTemplates: Dictionary<WrappedTemplateName, HtmlNode>) =
          for n in nodes do
              let templateName = n.GetAttributeValue(ChildrenTemplateAttr, "")
              let w = WrappedTemplateName(templateName)
              if wsTemplates.ContainsKey w then
                  failwithf "Template defined multiple times: %s" templateName
              wsTemplates.Add(w, detachChildrenTemplateNode n)
  
      let parseNodeAsTemplate fileId (n: HtmlNode) =
          match n.Attributes.[HoleAttr] with
          | null ->
              let instState = ParseState(fileId)
              match n with
              | Instantiation instState el ->
                  {
                      Value = [| el |]
                      Holes = instState.Holes
  