From what I gather, you are aiming to create a directive that can highlight code provided as a constant, dynamically through variables, or a combination of both. If you are open to different syntax options, here is a potential solution.
The main issue lies in the fact that before applying Prism's highlight function, the code template must be compiled to replace {{variables}} with their corresponding values. In your current approach, the highlight function is being applied directly to the raw template.
The suggested approach involves changing the binding type from '=' to '@' and passing the source code as an attribute in all scenarios.
Previous binding:
scope: {
source: '='
}
New binding:
scope: {
source: '@'
}
Refer to Angular documentation for more information on bindings.
@ or @attr - bind a local scope property to the value of DOM attribute. The result is always a string since DOM attributes are strings. If no attribute name is specified, it is assumed to be the same as the local name. For example, with scope: { localName:'@myAttr' }, the widget scope property localName will reflect the interpolated value of hello {{name}}. As the name attribute changes, so will the localName property on the widget scope.
Here is an updated HTML sample (note that the old binding from the initial example has also been modified):
<!-- This works -->
<pre nag-prism source="{{code}}" class="language-css"></pre>
<!-- Now this works too! -->
<pre nag-prism source="body {
color: red;
}
{{code}}" class="language-css"></pre>
Complete revised directive code:
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>"
};
}]);
You can view a working solution here: working sample
Edit: The directive has been updated to meet the target mentioned in the comment below.
To properly display transcluded content, manual compilation is required. This results in some adjustments to the directive code (the version below uses transcluded content if it is not empty and the source is not defined):
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>"
};
}]);
This sample includes a code block bound to input to demonstrate that linking functions correctly: improved sample