在角应用中使用prismjs

时间:2014-03-30 10:30:58

标签: javascript angularjs angularjs-directive

我正试图在我的角度应用中使用prismjs 这是我到目前为止所得到的

app.directive('nagPrism', [function() {
    return {
        restrict: 'A',
        transclude: true,
        scope: {
            source: '='
        },
        link: function(scope, element, attrs, controller, transclude) {
            if(!scope.source) {
                transclude(function(clone) {
                    element.html(clone);
                    Prism.highlightElement(element.find("code")[0]);
                });
            } else {
                scope.$watch(function() {return scope.source;}, function(v) {
                    if(v) {
                        Prism.highlightElement(element.find("code")[0]);
                    }
                });
            }

        },
        template: "<code ng-bind='source'></code>"
    };

}]);

如果我有这样的东西,这将有效

<!-- This works  -->
<pre nag-prism source="code" class="language-css"></pre>

但是我想让它也适合这样的事情

<pre nag-prism class="language-css">
<code>body {
color: red; 
}
  {{code}}

</code>
</pre>

为方便起见,我做了一个plunkr 有什么提示吗?

3 个答案:

答案 0 :(得分:9)

据我所知,你的目标是构建一个突出显示代码的指令,这些代码既可以作为常量给定,也可以通过变量或上面两种混合使用。如果您没有附上帖子的语法,这里有解决方案。

主要问题是在应用Prism高亮显示功能之前,需要编译代码模板以便将{{variables}}更改为它们的值。在您的解决方案中,突出显示功能将应用于原始模板。

我们的想法是将绑定类型从'='更改为'@',并在所有情况下将源代码作为属性传递。

旧约束:

scope: {
    source: '='
}

新绑定:

scope: {
    source: '@'
}

Angular文档:

  

@或@attr - 将本地范围属性绑定到DOM的值   属性。由于DOM属性,结果总是一个字符串   字符串。如果未指定attr名称,则属性名称为   假设与本地名称相同。给定和小部件定义   范围:{localName:'@ myAttr'},然后是widget范围属性   localName将反映hello {{name}}的内插值。如   name属性更改,因此localName属性将更改   小部件范围。从父作用域(而不是组件)读取名称   范围)。

更新了html示例(请注意第一个示例中的旧绑定也已更改!):

<!-- This works  -->
<pre nag-prism source="{{code}}" class="language-css"></pre>

<!-- Now this works either!  -->
<pre nag-prism source="body {
    color: red; 
}
{{code}}" class="language-css"></pre>

完整更新的指令代码:

app.directive('nagPrism', [function() {
    return {
        restrict: 'A',
        scope: {
            source: '@'
        },
        link: function(scope, element, attrs) {
            scope.$watch('source', function(v) {
                if(v) {
                    Prism.highlightElement(element.find("code")[0]);
                }
            });
        },
        template: "<code ng-bind='source'></code>"
    };
}]);

您可以在此处找到有效的解决方案:working sample

编辑:指示已更新,以符合以下评论中的目标

为了正确显示已删除的内容,必须手动编译。它会导致指令代码发生一些变化(如果版本不为空且未定义源,则下面的版本使用已转换的内容):

app.directive('nagPrism', ['$compile', function($compile) {
    return {
        restrict: 'A',
        transclude: true,
        scope: {
          source: '@'
        },
        link: function(scope, element, attrs, controller, transclude) {
            scope.$watch('source', function(v) {
              element.find("code").html(v);

              Prism.highlightElement(element.find("code")[0]);
            });

            transclude(function(clone) {
              if (clone.html() !== undefined) {
                element.find("code").html(clone.html());
                $compile(element.contents())(scope.$parent);
              }
            });
        },
        template: "<code></code>"
    };
}]);

以下示例添加了绑定到输入的代码块,以显示链接有效:improved sample

答案 1 :(得分:4)

您只需要在执行控制器后重新加载Prism插件。

app.controller('StartController', ['$scope', function($scope){

 console.log('hello');

 Prism.highlightAll(); // Only this that you need do!

}]);

答案 2 :(得分:0)

将其添加到$ stateChangeSuccss事件处理程序

app.run(function($rootScope $timeout){
$rootScope.$on('$stateChangeSuccess', function() {
  $timeout(function() {Prism.highlightAll()}, 0);
});