Reputation: 266978
I want to use the showdownjs javascript markdown library using Rhino.
It is used like this:
var Showdown = require('showdown');
var converter = new Showdown.converter();
converter.makeHtml('#hello markdown!');
// <h1 id="hellomarkdown">hello, markdown</h1>
So I have the showdown.js file (https://raw.githubusercontent.com/showdownjs/showdown/master/compressed/Showdown.js), how would I go about calling this makeHTML
method, while passing it a parameter that i have on the jvm side?
I found this code snippet online:
import org.mozilla.javascript.Scriptable
import org.mozilla.javascript.ScriptableObject
import org.mozilla.javascript.{Context, Function}
import java.io.InputStreamReader
class Showdown {
def markdown(text: String): String = {
// Initialize the Javascript environment
val ctx = Context.enter
try {
val scope = ctx.initStandardObjects
// Open the Showdown script and evaluate it in the Javascript
// context.
val showdownURL = getClass.getClassLoader.getResource("showdown.js")
val stream = new InputStreamReader(showdownURL.openStream)
ctx.evaluateReader(scope, stream, "showdown", 1, null)
// Instantiate a new Showdown converter.
val converterCtor = ctx.evaluateString(scope, "Showdown converter", "converter", 1, null).asInstanceOf[Function]
val converter = converterCtor.construct(ctx, scope, null)
// Get the function to call.
val makeHTML = converter.get("makeHtml", converter).asInstanceOf[Function]
val htmlBody = makeHTML.call(ctx, scope, converter, Array[AnyRef](text))
htmlBody.toString
}
finally {
Context.exit
}
}
}
When I use it like this:
val s = new Showdown()
s.markdown("hello")
I get an error:
org.mozilla.javascript.EvaluatorException: missing ; before statement (converter#1)
at org.mozilla.javascript.DefaultErrorReporter.runtimeError(DefaultErrorReporter.java:109)
at org.mozilla.javascript.DefaultErrorReporter.error(DefaultErrorReporter.java:96)
at org.mozilla.javascript.Parser.addError(Parser.java:146)
at org.mozilla.javascript.Parser.reportError(Parser.java:160)
at org.mozilla.javascript.Parser.statementHelper(Parser.java:1266)
at org.mozilla.javascript.Parser.statement(Parser.java:707)
at org.mozilla.javascript.Parser.parse(Parser.java:401)
at org.mozilla.javascript.Parser.parse(Parser.java:338)
at org.mozilla.javascript.Context.compileImpl(Context.java:2368)
at org.mozilla.javascript.Context.compileString(Context.java:1359)
at org.mozilla.javascript.Context.compileString(Context.java:1348)
at org.mozilla.javascript.Context.evaluateString(Context.java:1101)
I've never used Rhino before so I am not sure what the issue is.
Does this line in my method look correct?
val converterCtor = ctx.evaluateString(scope, "Showdown converter", "converter", 1, null).asInstanceOf[Function]
Upvotes: 4
Views: 453
Reputation: 911
This should do the trick
load('./Showdown.js');
var s = Showdown
print(s);
var c = new s.converter();
//print(s.converter);
print(c.makeHtml('#hello markdown!'));
Hope it helps
Upvotes: 0
Reputation: 516
The call you have to evaluateString looks incorrect to me. The second and third arguments to evaluateString have been swapped accidentally. The second argument should be the script you need to execute (see http://www-archive.mozilla.org/rhino/apidocs/org/mozilla/javascript/Context.html#evaluateString(org.mozilla.javascript.Scriptable, java.lang.String, java.lang.String, int, java.lang.Object)). It should read:
val converterCtor = ctx.evaluateString(scope, ***SCRIPT GOES HERE***, **DESCRIPTION GOES HERE***, 1, null).asInstanceOf[Function]
In fact give that all you're going to do is construct the converter, you can save yourself the call to construct() by having evaluateString return a constructed object to you:
var converter = ctx.evaluateString(scope, "new Showdown.converter();", "Showdown converter", 1, null).asInstanceOf[Function]
You can then call makeHTML as in your code above.
Upvotes: 0
Reputation: 1002
Use Rhino's built-in load()
function, used to load external JS files into the Rhino JavaScript environment.
load([filename, ...])
Load JavaScript source files named by string arguments. If multiple arguments are given, each file is read in and executed in turn.
From the Official Mozilla Rhino Docs.
For example, if I wanted to use a JavaScript function stored within another class, I would do so like this:
The external file (For the sake of the example, called testFile.js
):
//Example Class testFile.js
function sayHi(){
Packages.java.lang.System.out.println('hi');
}
The actual code (Standard java, not scala) for running the sayHi()
function:
Context ctx = Context.enter();
Scriptable scope = ctx.initStandardObjects();
Object o = ctx.evaluateString(scope,
"load('testFile.js');
sayHi();",
1,
null);
This will import the testFile.js
file, and run the sayHi()
function, which accesses the java.lang.System
class, and executes the out.println(args)
method, with the args hi
.
Upvotes: 2