Разница между предкомпилирующим и посткомпилирующим элементом в директивах AngularJS?

В настоящее время я пишу несколько директив Angular, которые меняют свои шаблоны в зависимости от определенных атрибутов. Они выглядят структурно так:

app.directive('mydir', function ($compile) {
    return {
        restrict: 'E',
        replace: true,
        transclude: true,
        compile: function (elem, attrs, transclude) {
            var replacement;
            // operations
            return function (scope, lElem, lAttrs) {
                transclude(scope, function (clone, scope) {
                    // more operations
                });
                elem.replaceWith($compile(replacement)(scope));  // IMPORTANT
            };
        }
    };
});

и находятся на этом Plunkr. Теперь, как написано (хорошо, сфокусировано), эти директивы не работают, если вы пытаетесь их вложить. Внутренняя директива заканчивается тем, что ее полностью исключенные элементы. Однако, если я заменил elem.replaceWith(...) на lElem.replaceWith(...) (в строке 36 файла Javascript в Plunkr), все будет в порядке, и я могу вложить столько раз, сколько захочу. Почему это происходит? В чем тут разница? Я понимаю, что elem не скомпилирован и lElem есть, но что это значит и как это влияет на мой код? Кроме того, разве не обескураживают манипуляции с DOM в функции link?

Что я пробовал. Я попытался отлаживать это сам, и похоже, что для внутренней директивы функция компиляции вызывается дважды (я бы предположил, что один раз из любого Angular и один раз с того момента, когда я использую $compile на нем), при первом компиляции все правильно, а во второй раз все неправильно. Но я не могу заставить его компилировать один раз, не удаляя инструкцию $compile, которая нарушает все! Похоже, что Angular скомпилирует все "на обратном пути" (то есть сначала детей) и связывает все "по пути вниз" (то есть родители сначала), но я не могу это подтвердить. По подозрению я попытался вернуть функцию prelink вместо функции postlink, но безрезультатно. Я также попытался поставить вызов elem.replaceWith(...) перед функцией link и скомпилировать дочерние элементы внутри функции link, но это тоже не сработало.

Что я думаю, что происходит. Я полагаю, что включение функции пересылки в функцию ссылок приводит к запутыванию всего (хотя я вынужден, потому что compile не имеет области видимости), принимая старый клон внутри директива и по какой-либо причине удалять ее дочерние элементы (elem и lElem, например, не имеют детей). Я не уверен, как подтвердить это или как его исправить, как только он подтвердится. Я предварительно провел некоторое тестирование, введя $rootScope и выполнив все ссылки и т.д. В функции компиляции, и ничего не получилось. Я не уверен, есть ли какие-либо различия между компиляцией и компиляцией с областью содержимого.