Closed ntopulos closed 8 years ago
I have a similar problem. I have a showdown extension which is dependent upon scope variables. For instance, in GitHub MD #25
actually refers to https://github.com/showdownjs/ng-showdown/issues/25
(ex #25), although before rendering a link to that url you need to have the context of the URL. Which is only available on the scope level. My idea was to insert a directive as above which would contextually fetch the url and append the id
but the HTML isn't compiling.
Perhaps there is a better approach?
Here's what I ended up with @ntopulos, hopefully this helps.
I created my own markdown
directive as an alternative to the mardown-to-html
directive:
// directive/markdown/markdown.js
'use strict';
angular.module('myApp')
.directive('markdown', function($showdown, $sanitize, $sce) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
scope.$watch('model', function (newValue) {
var showdownHTML;
if (typeof newValue === 'string') {
showdownHTML = $showdown.makeHtml(newValue);
scope.trustedHtml = ($showdown.getOption('sanitize')) ? $sanitize(showdownHTML) : $sce.trustAsHtml(showdownHTML);
} else {
scope.trustedHtml = typeof newValue;
}
});
},
scope: {
model: '=markdown'
},
template: '<div bind-html-compile="trustedHtml"></div>'
};
});
Please note that this is an exact copy of the markdown-to-html
directive with the exception of this: template: '<div bind-html-compile="trustedHtml"></div>'
.
With that being done, I created another directive bind-html-compile
which compiled the html given to it which looks like so:
// directive/bindHtmlCompile/bindHtmlCompile.js
'use strict';
angular.module('myApp')
.directive('bindHtmlCompile', function($compile) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
scope.$watch(function() {
return scope.$eval(attrs.bindHtmlCompile);
}, function(value) {
element.html(value);
$compile(element.contents())(scope);
});
}
};
});
Usage:
<!-- instead of this: -->
<div markdown-to-html="myMarkdown"></div>
<!-- use this: -->
<div markdown="myMarkdown"></div>
Voilà!
Additionally, to keep my organization a little cleaner, I created the showdown extensions
as angular constants like so:
// constants/myExt.js
(function(){
'use strict';
angular.module('myApp')
.constant('myExt',
function myExt() {
var myext1 = {
type: 'lang',
regex: /markdown/g,
replace: 'showdown'
};
var myext2 = {
/* extension code */
};
return [myext1, myext2];
});
})();
And then injected and registered them in the config:
// app.js
.config(function($showdownProvider, myExt) {
$showdownProvider.setOption('tables', true);
//...
$showdownProvider.loadExtension(myExt);
//...
})
Hope this helps!
Here's a custom video extension I created:
(function () {
var videoHTML = '<video video-data="someAngularVarriableLocalToThisPage"></video>';
function video() {
var replace = function () {
return videoHTML;
};
return [
// Inline style
{
type: 'lang',
regex: '\\[\\s*?!\\[[^()]*\\([^\\(]*\\s*?\\(.* "video"\\)',
replace: replace
}];
}
// Client-side export
if (showdown && showdown.extensions) {
showdown.extensions.video = video;
}
})();
To load this into ng-showdown, you can reference it like so. (The way @jspizziri did it works too!)
angular
.module('example')
.config(function ($showdownProvider) {
$showdownProvider.loadExtension('video');
});
There a few things I'm doing here:
<video video-data="someVar"></video>
someVar
already exists on the page that the markdown is running on.Does this help? I think @jspizziri answered most of the questions, I just wanted to share how I've done it as well.
Thank you both for your replies! Unfortunately I wasn't able to make it work, what do I miss?
I've created these jsfiddles, and as you can see the directive is never executed when generated by a ShowDown extension:
In each example I use the extension to replace &test
inside the markdown string by <simple-element>extension: executed, directive: NOT executed</simple-element>
. Then the SimpleElement
directive should replace this by <div>directive executed</div>
, but it doesn't.
Actually @jspizziri's method worked! https://jsfiddle.net/ov0q23Le/1/
I thought it didn't because of a local issue with this line that I forgot to uncomment when creating the jsfiddle:
scope.trustedHtml = ($showdown.getOption('sanitize')) ? $sanitize(showdownHTML) : $sce.trustAsHtml(showdownHTML);
@SyntaxRules This thread has very good information. Do you mind creating a wiki entry with this info?
I was able to make a custom extension, but I couldn't find how to compile the contained directives.
The given tag is replaced, but the resulting HTML is not processed by Angular.
How to compile the result with Angular? I don't know if it is even possible to define a compilation from .config(). Should the extension be included somewhere else?
Here is a test extension replacing
&test
by'<simple-element></simple-element>
:The simpleElement directive: