Running JavaScript in an AsciidoctorJ extension

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Running JavaScript in an AsciidoctorJ extension

wimdeblauwe
Hi,

We are creating a custom visualization based on d3.js for a web application. I would like to be able to re-use that code to generate diagrams with that code and put the resulting SVG in a HTML or PDF document. My idea is to use the Nashorn JavaScript engine from Java8 to make that possible.

So far, I managed to create a simple extension that executes some simple JavaScript:

public class JavaScriptExecutionBlock extends BlockProcessor {

    private static final ScriptEngine SCRIPT_ENGINE = new ScriptEngineManager().getEngineByName("nashorn");

    public JavaScriptExecutionBlock(String name, Map<String, Object> config) {
        super(name, createConfig());
    }

    @Override
    public Object process(AbstractBlock parent, Reader reader, Map<String, Object> attributes) {
        String jsResult;
        try {
            jsResult = SCRIPT_ENGINE.eval(reader.read()).toString();
        } catch (ScriptException e) {
            e.printStackTrace();
            jsResult = e.getMessage();
        }
        return createBlock(parent, "paragraph", jsResult, attributes, new HashMap<>());
    }

    private static Map<String, Object> createConfig() {
        Map<String, Object> result = new HashMap<>();
        result.put("contexts", createContextsConfig());
        return result;
    }

    private static List<String> createContextsConfig() {
        List<String> contexts = new ArrayList<>();
        contexts.add(":open");
        return contexts;
    }
}

Using this BlockProccessor, it will transform this:

[javascript-exec]
--
2+2
--

by running the addition in Javascript and outputting the result.

I am wondering how to do the next steps, so I could use some guidance.

The visualization is similar to drawing an UML diagram, so I will explain it like that. Suppose I put this in the input asciidoc document:

[my-custom-visualization-extension]
--
BlockProcessor -> Processor
--

Suppose further that I have a JavaScript file with a method that accepts 'BlockProcessor -> Processor' and returns an SVG string. Given the code from https://stackoverflow.com/a/22648888/40064 I should be able to load those JavaScript files and execute the function.

2 main questions:
* How do I code the fact that I am returning SVG in the process method of my BlockProcessor? I am currently using something like: createBlock(parent, "paragraph", jsResult, attributes, new HashMap<>()); Do I need to use something else than "paragraph" ?
* Are there any ideas how I could make this a re-usable extension where you could somehow indicate in the document what JavaScript files you want to load and what function you want to call? How could this be indicated in an asciidoc source file?

regards,

Wim