Markdown syntax highlighting in Javascript - javascript

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 accomplished?

Author of marked here. I addressed this a while ago on the issue tracker: https://github.com/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.com/chjj/marked/issues/47#issuecomment-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.

Related

Monaco Editor (TypeScript): Decorate JSDoc or TSDoc with further buttons/links/actions

I'm using Microsoft Monaco Editor for TypeScript language. The TypeScript classes and functions have JSDoc. I'd like to add buttons/links/etc. to the existing JSDoc in order to invoke a JavaScript function when the user clicks on them in the code completion.
It seems that I cannot simply put HTML with JavaScript into the existing JSDoc. Is it possible to attach any buttons to the JSDoc displayed by the code completion, belatedly? I want to add them to the already existing JSDoc.
https://microsoft.github.io/monaco-editor/playground.html
const editor = monaco.editor.create(document.getElementById("container"), {
value: "/** This is the basic JSDoc <span onclick='alert()'>my button</span>*/" +
"function hello(param: number): string {\n\talert('Hello world!');\nreturn '';\n}",
language: "typescript"
});
monaco.languages.registerCompletionItemProvider('javascript', {
resolveCompletionItem: function(item, token) {
alert(item);
}
});
This is not possible. The API for completion items only accepts markdown text (or plain text), not HTML.
While I agree with the original answer saying that this isn't possible because the API will never render HTML, you could still go a long way decorating with plain Markdown. And intercepting undesirable API behaviors is pretty much the whole reason why the Proxy object exists.

SonarQube JavaScript disable a part of code

I would like to disable a block of code(say a function) in a file for analysis by SonarQube... Any suggestions on how to do that..
I found something for java here --> Turning Sonar off for certain code
As far as I know Sonar respects // NOSONAR tag for Java projects but it looks like that is also has been implemented for JS: https://jira.sonarsource.com/browse/SONARJS-294
SonarQube provides plenty of options for ignoring issues in specific files and/or code blocks, see Narrowing the Focus documentation (and to your specific case: look for Ignore Issues in Blocks).
To ignore blocks:
// BEGIN-NOSCAN
const YourFunction () => {
// Your code
}
// END-NOSCAN
To ignore single lines:
// NOSONAR
const YourCode = 'Example';
You can read more about it here in the SonarQube docs Narrowing the Focus. Thanks to Jan and Nicolas's answer above.

I need a simple way to avoid callback nests in javascript

I have a NPAPI plugin that I changed to native messaging, NPAPI is synchronous and so was the plugin. since chrome ditched NPAPI for good
Now that I have to change it to asynchronous calls, I am trying to find a way to handle the callbacks . I have wrapped the messaging into a class to handle a specific message from content script to background script.
I am handling the callbacks inside the class through setting it to internal array of callbacks functions as well as function specific result callbacks
However I am find difficulty in changing page code
as an example
lets assume the old code was like
res = npClass.function1 (var1,var2);
if(res == 'someval')
npClass.function2()
npClass.function1(var2,res.substring(2,3))
and so on
now that all functions are async I have to change the code to be more or less like this
npClass.function1(var1,var2, function(res)
{
if(res == 'someval')
npClass.function2(function(){
npClass.function1(var2,res.substring(2,3), function(res)
{});
npClass.function1(var2,res.substring(2,3);
}
}
and the nesting will go on and on this isn't how I expect it to be.
All I can think of is right now is that may be if I change the page code to make the parts of code that uses the extension as a class that inherits from the other message handling class then I can use the internal structure to invoke callbacks on the new class callbacks in messaging class
But even if I do this my code will be very fragmented
it will be something like this
PageClass.prototype.functionL()
{
functions1(functionb) 'from inheritance
}
PageClass.functionb(res)
{
if(res == 'some value)
function2( functionq) 'from inheritance
}
Still this is not suitable for me and I am sure I will have to handle a lot of stuff in it plus this will require a huge change in the structure of the page code.
I have searched all around to find any way to make async call sync in javascript but didn't find any plausible solution.
I am not expert in javascript and I need ideas to explore,
can someone here guide me

How should I mark a method as "obsolete" in JS?

I am refactoring a rather large JS file that contains many unrelated methods into something that will regroup the methods together according to their usage, and renaming some of them as needed (to prevent misleading names).
However, most of the web pages that actually use this code are spread across different code branches, preventing me from doing a simple find&replace. I could do it in all the different branches, but that requires doing maintenance in 30+ branches at the same time, or probably forgetting to perform the renaming once the change is merged in the other branches (by me or other team members).
If this was C#, I could just mark the method with [Obsolete] and it would flag the necessary changes as needed, so I am looking for something somewhat equivalent. I will still provide functionality with the old interface for a while by just redirecting the calls to the new methods, but I'd like to "force" people to switch to the new interface as they work on the pages for other reasons.
Is there any other way to do something similar, besides adding a debugger;
statement and a verbose comment to every method so that it breaks when developing but not in production?
There are a couple of things you can do in a transition period.
Add the #deprecated JSDoc flag.
Add a console warning message that indicates that the function is deprecated.
A sample:
/**
* #deprecated Since version 1.0. Will be deleted in version 3.0. Use bar instead.
*/
function foo() {
console.warn("Calling deprecated function!");
bar();
}
Here's what we've found for Visual Studio 2013 : http://msdn.microsoft.com/en-us/library/vstudio/dn387587.aspx
It's not tested yet as we haven't made the switch, but it looks promising.
In the meantime, I am inserting a flag at page load depending on context such as :
<%
#if DEBUG
Response.Write("<script type=\"text/javascript\"> Flags.Debug = true; </script>");
#endif
%>
and then I call a method that throws an error if the flag is true, or redirect to the new call if it is in release configuration.
function obsolete(oldFunc, newFunc) {
const wrapper = function() {
console.warn(`WARNING! Obsolete function called. Function ${oldFunc.name} has been deprecated, please use the new ${newFunc.name} function instead!`)
newFunc.apply(this, arguments)
}
wrapper.prototype = newFunc.prototype
return wrapper
}

Minimalistic example of IPython kernel javascript bi-directional communication

My goal is to write an interactive variable viewer for IPython, i.e. which allows one to see, say nested dicts/lists as a tree, and drill down (a bit like the console.log in Javascript).
I spent a lot of time trying to extract minimalistic code out of the directview example in IPython but still can't get my head around how it all works. My Python's ok but my jQuery experience is quite limited.
So I got to stripping down directview.js to the following
container.show();
var widget = $('<div/>')
element.append(widget);
var output = $('<div></div>');
$(widget).append(output)
var output_area = new IPython.OutputArea(output, false);
var callbacks = { 'output': $.proxy(output_area.handle_output, output_area) };
var code = 'print 1+1'
var msg_id = IPython.notebook.kernel.execute(code, callbacks, {silent: false});
This works when I load the directview.ipynb. However I am still not clear how to make it completely standalone (i.e. not require the directview.py, and pass another callback than the standard handle_output of IPython.OutputArea). One of the issues is the container.show() which fails when called in a standalone way.
I am lost on several aspects:
Why is there an element.append(widget) and then $(widget).append(output)? Also why is there also a need to create an Ipython.OutputArea. Isn't there a way to just create a <div id=my_output_area>blah</div> and then have the output callback fill it with the relevant data?
What's the whole .proxy thing about? I would like to create my own callback for output but when I do that and console.log() the arguments passed to the callback, they're undefined or just useless.
I appreciate that the authors of the IPython notebook have done an incredible job creating such a beautiful front-end using jQuery/websockets, and that creating developer documentation that allows beginners like me to tweak with it is asking much, but if anyone can lend a hand that would be great!
I can answer to your second question. The fact is when JavaScript calls your callback, it makes it so without specifying the context, i.e. without setting this (Pythonistas call it self). But it's possible to bound a function to this via $.proxy, which you saw in:
var callbacks = { 'output': $.proxy(output_area.handle_output, output_area) };

Categories