I am trying to get the rainbow syntax highlighting library to work with the marked markdown rendering engine. The marked
documentation states that a syntax highlighter is supported through the following configuration option:
marked.setOptions({
highlight: function(code, lang) {
return highlighter.javascript(code);
}
});
The rainbow
source code indicates that passing in a string to highlight is supported via the following syntax:
Rainbow.color(code, lang, success);
I'm a bit at a loss as to how to put the two together. Specifically, success
is a callback that will be called asynchronously, and I can't simply return the value from the Rainbow.color
code inside the highlight
callback. How would this be acplished?
I am trying to get the rainbow syntax highlighting library to work with the marked markdown rendering engine. The marked
documentation states that a syntax highlighter is supported through the following configuration option:
marked.setOptions({
highlight: function(code, lang) {
return highlighter.javascript(code);
}
});
The rainbow
source code indicates that passing in a string to highlight is supported via the following syntax:
Rainbow.color(code, lang, success);
I'm a bit at a loss as to how to put the two together. Specifically, success
is a callback that will be called asynchronously, and I can't simply return the value from the Rainbow.color
code inside the highlight
callback. How would this be acplished?
- You need something like usbfirewire./uconverters.html but for CPS transformations... – 6502 Commented Feb 17, 2013 at 22:09
-
Cool. Does that have anything to do with
$.Deferred
? – user2398029 Commented Feb 17, 2013 at 22:10 -
I don't think so. The problem is that marked seems to require a synchronous syntax highlighter and there's no way to transform an asynchronous one like rainbow in a synchronous one (that's why for example many
node.js
lib functions provide also a "...Synch" version... there's no way to build one from Javascript). See stackoverflow./q/6842256/320726 – 6502 Commented Feb 17, 2013 at 22:14
4 Answers
Reset to default 9 +50Author of marked here. I addressed this a while ago on the issue tracker: https://github./chjj/marked/issues/47
It's more than possible to use an asynchronous highlighter with marked. You'll just have to iterate over the tokens the lexer spits out.
Example here: https://github./chjj/marked/issues/47#issuement-5297067 (Keep in mind this is an example. You'll have to modify it a bit.)
I might just implement this natively in marked using the method in the link above. It will be a performance hit to the people using async highlighters, but if you need an async highlighter, that means the highlighter is doing some kind of IO and you're already taking a performance hit.
You could try using another highlighting library, such as highlight.js - It has synchronous highlighting methods (hljs.highlight(lang, code).value
and hljs.highlightAuto(code).value
) that you can use in the browser like this:
marked.setOptions({
highlight: function(code) {
return hljs.highlightAuto(code).value;
}
});
Here's a working JsFiddle example.
Unfortunately there's no way to solve the problem.
marked
seems to require a synchronous syntax highlighter, and rainbow
is an asynchronous syntax highlighter.
In Javascript there's no way to convert the latter to the former.
This is for example the reason why in node.js
for many library functions there are both a synchronous and an asynchronous version. There's no way in Javascript to build a synchronous one given only the asynchronous one because you cannot create a "nested event loop" (in some cases the opposite conversion instead can be done using web workers).
May be it's not difficult to add the synchronous version to rainbow
(e.g. by providing beforehand the external resources that it is probably loading asynchronously).
Not the perfect solution, but until the synchronous API has been merged into rainbow.js I solved it with the code below:
// ... after marked() has converted the markdown to html
// (the highlight option of marked should be unchanged!)
// find all <code> elements and go through each
$('body')
.find('code')
.each(function() {
var $code = $(this),
cls = $code.attr('class'),
language;
// no language information at all
if(typeof cls === 'undefined') {
return;
}
// actually we should also check if a valid "lang-" class
// (which is by default set through marked) is given
language = cls.split('-')[1];
// add the data-language to the <code> element
$code.data('language', language);
});
// let the rainbows shine
Rainbow.color();
This runs client side and uses jQuery.