Pagedown through ScriptEngine incorrect parsing Markdown

I try to use PageDown on the client side as an editor, and on the server side I parse that Markdown to HTML.

It seems to work fine on the client side, but on the server side, tickmarks only β€œencode” the subsequent character, not the word that it wraps. Therefore, if I do this:

test `test` test

I expect this, and this is really what I get on the client side:

test <code>test</code> test

But on the server side, I get this instead:

test <code>t</code>est<code> </code>test

I created a file called pageDown.js , which is simply Markdown.Converter.js and Markdown.Sanitizer.js combined into one file, adding this function:

 function getSanitizedHtml(pagedown){ var converter = new Markdown.getSanitizingConverter(); return converter.makeHtml(pagedown); } 

On the client side, I can use this file as follows:

 <!DOCTYPE html> <html> <head> <script src="pageDown.js"></script> <script> function convert(){ var html = getSanitizedHtml("test `test` test"); console.log(html); document.getElementById("content").innerHTML = html; } </script> </head> <body onload="convert()"> <p id="content"></p> </body> </html> 

This displays correctly: <p>test <code>test</code> test</p>

On the server side (Java), I use the exact same file through the Java ScriptEngineManager and Invocable :

 import java.io.InputStreamReader; import javax.script.Invocable; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; public class PageDownTest{ public static void main(String... args){ try{ ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("JavaScript"); engine.eval(new InputStreamReader(PageDownTest.class.getResourceAsStream("pageDown.js"))); Invocable inv = (Invocable) engine; String s = String.valueOf(inv.invokeFunction("getSanitizedHtml", "test `test` test")); System.out.println(s); } catch(Exception e){ e.printStackTrace(); } } } 

This program prints this: <p>test <code>t</code>est<code></code>test</p>

I see similar problems with other markdowns: test **test** test just ignores the ** part. However, ##test returns correctly as <h2>test</h2> .

All this works great if I go to JavaScript directly through HTML, but not when navigating through Java. What's going on here? Should I handle Markdown on the server differently?

+5
source share
1 answer

I was able to reduce the problem to the following code:

 function getSanitizedHtml(text) { return text.replace(/(a)(?!b)\1/gm, 'c'); } 

When called in browser

 getSanitizedHtml('aa'); 

it returns:

 c 

When called from the Nashorn engine as

 String s = String.valueOf(inv.invokeFunction("getSanitizedHtml", "aa")); 

it returns:

 cc 

For me, it looks like backreference \1 , which should point to (a) , instead point to (?!b) , the captured content of which is of zero length and thus matches something.

Equivalent code in Java:

 System.out.println(("aa").replaceAll("(a)(?!b)\\1", "c")); 

returns the correct result:

 c 

Conclusion

I am sure this is a bug in the Nashorn engine.
I submitted a bug report and posted it here if it becomes publicly available.

As for your problem, I think your only option is to switch to another JavaScript environment, at least temporarily.

Minimal running examples

JS in browser:

 function x(s){return s.replace(/(a)(?!b)\1/gm, 'c');} document.write(x('aa')); 

JS in the Nashrhor engine:

[ Ideone ]

Pure Java:

[ Ideone ]

Possible fix

As already mentioned, the only option (at this stage) is to switch to another JavaScript environment.
There are many available and Wikipedia comparison pages . In this example, I chose io.js (I hope you can install it yourself).

If you want to use the pageDown.js file, you will first need to comment on the exports checks and use simple old variables, for example:

 /*if (typeof exports === "object" && typeof require === "function") // we're in a CommonJS (eg Node.js) module Markdown = exports; else*/ Markdown = {}; 

and

 /*if (typeof exports === "object" && typeof require === "function") { // we're in a CommonJS (eg Node.js) module output = exports; Converter = require("./Markdown.Converter").Converter; } else {*/ output = Markdown; Converter = output.Converter; //} 

(Note that I also changed output = window.Markdown; to output = Markdown; - you should have done the same (Nashorn would have given you an error otherwise), but just forgot to mention this in your question.)

Alternatively, of course, you can use the export system and individual files, but I have no experience with this, so I will do it like this.

Now io.js accepts JavaScript code from stdin, and you can write to stdout via process.stdout.write() , so we can do the following (on the command line):

 { cat pageDown.js; echo 'process.stdout.write(getSanitizedHtml("test `test` test"));'; } | iojs; 

And we get the following answer:

 <p>test <code>test</code> test</p> 

If you need to do this with Java, you can do it like this:

 import java.io.*; class Test { public static void main(String[] args) throws Exception { Process p = Runtime.getRuntime().exec("/path/to/iojs"); OutputStream stdin = p.getOutputStream(); InputStream stdout = p.getInputStream(); File file = new File("/path/to/pageDown.js"); byte[] b = new byte[(int)file.length()]; FileInputStream in = new FileInputStream(file); for(int read = 0; read < b.length; read += in.read(b, read, b.length - read)); // <-- note the semicolon stdin.write(b); stdin.write("process.stdout.write(getSanitizedHtml('test `test` test'));".getBytes()); stdin.close(); // <-- important to close p.waitFor(); b = new byte[stdout.available()]; stdout.read(b); System.out.println(new String(b)); } } 

Pay attention to the semicolon immediately after for (therefore, it only read += in.read(b, read, b.length - read) each time and nothing more), and also note that when calling .close() in a thread is usually optional, since this will be done automatically when the object goes out of scope, stdin.close() must be called stdin.close() , or iojs will continue to wait for input, and p.waitFor() will never return.

+4
source

All Articles