function compileNodes(nodeList, transcludeFn, rootElement, maxPriority) {
     var linkingFns = [],
         directiveLinkingFn, childLinkingFn, directives, attrs, linkingFnFound;

     for(var i = 0; i < nodeList.length; i++) {
       attrs = new Attributes();

       // we must always refer to nodeList[i] since the nodes can be replaced underneath us.
       directives = collectDirectives(nodeList[i], [], attrs, maxPriority);

       directiveLinkingFn = (directives.length)
           ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, rootElement)
           : null;

       childLinkingFn = (directiveLinkingFn && directiveLinkingFn.terminal)
           ? null
           : compileNodes(nodeList[i].childNodes,
                directiveLinkingFn ? directiveLinkingFn.transclude : transcludeFn);

       linkingFns.push(directiveLinkingFn);
       linkingFns.push(childLinkingFn);
       linkingFnFound = (linkingFnFound || directiveLinkingFn || childLinkingFn);
     }

     // return a linking function if we have found anything, null otherwise
     return linkingFnFound ? linkingFn : null;

     /* nodesetLinkingFn */ function linkingFn(scope, nodeList, rootElement, boundTranscludeFn) {
       var childLinkingFn, directiveLinkingFn, node, childScope, childTransclusionFn;

       for(var i=0, n=0, ii=linkingFns.length; i<ii; n++) {
         node = nodeList[n];
         directiveLinkingFn = /* directiveLinkingFn */ linkingFns[i++];
         childLinkingFn = /* nodesetLinkingFn */ linkingFns[i++];

         if (directiveLinkingFn) {
           if (directiveLinkingFn.scope) {
             childScope = scope.$new(isObject(directiveLinkingFn.scope));
             jqLite(node).data('$scope', childScope);
           } else {
             childScope = scope;
           }
           childTransclusionFn = directiveLinkingFn.transclude;
           if (childTransclusionFn || (!boundTranscludeFn && transcludeFn)) {
             directiveLinkingFn(childLinkingFn, childScope, node, rootElement,
                 (function(transcludeFn) {
                   return function(cloneFn) {
                     var transcludeScope = scope.$new();

                     return transcludeFn(transcludeScope, cloneFn).
                         bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));
                    };
                  })(childTransclusionFn || transcludeFn)
             );
           } else {
             directiveLinkingFn(childLinkingFn, childScope, node, undefined, boundTranscludeFn);
           }
         } else if (childLinkingFn) {
           childLinkingFn(scope, node.childNodes, undefined, boundTranscludeFn);
         }
       }
     }
   }
Compile function matches each node in nodeList against the directives. Once all directives
for a particular node are collected their compile functions are executed. The compile
functions return values - the linking functions - are combined into a composite linking
function, which is the a linking function for the node.

@param {NodeList} nodeList an array of nodes to compile
@param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the
       scope argument is auto-generated to the new child of the transcluded parent scope.
@param {DOMElement=} rootElement If the nodeList is the root of the compilation tree then the
       rootElement must be set the jqLite collection of the compile root. This is
       needed so that the jqLite collection items can be replaced with widgets.
@param {number=} max directive priority
@returns {?function} A composite linking function of all of the matched directives or null.