1

In my architecture Javascript code is generated in the server. A huge chunk of Javascript code is generated, stored in a java.lang.String and sent to the client side. I want to more easily debug the generated code (both the generation and how it runs).

Someone knows an easy way to format Javascript code?

flybywire
  • 261,858
  • 191
  • 397
  • 503
  • 1
    see http://stackoverflow.com/questions/351298/best-source-code-formatter-for-javascript –  Oct 24 '11 at 15:02
  • 1
    *"Javascript code is generated in the server."* (Shudder) Why is this JS even being generated using Java? I cannot think of a circumstance where the JS is not better left as external files which are read in by the HTML. Configure base conditions for the scripts using some trivial `var` attributes written to the page, and the job is done. – Andrew Thompson Oct 24 '11 at 17:59
  • 1
    @AndrewThompson By creating it on the server you open the door to interesting, concisely-defined behavior. As long as it's "invisible" (i.e., handled by app-/framework-specific code), I don't see an issue with it. It's a tool like any other. – Dave Newton Oct 24 '11 at 18:16
  • @Andrew, it has some good reasons, the most important one being that it is a legacy system with its amount of happy paying customers – flybywire Oct 25 '11 at 08:28

5 Answers5

5

It may be too late, but still.

I haven't found popular Java libraries for doing what you want; however, there are many javascript libraries for that (for example, js-beautify). You can save such library source code in resources of your application (you can get the code from one of cdn links, so you don't have to group and minify it manually), and then load it and invoke it with the Nashorn javascript engine.

Your code may look like this (roughly):

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.InputStreamReader;

public class JavascriptBeautifierForJava {

    // my javascript beautifier of choice
    private static final String BEAUTIFY_JS_RESOURCE = "beautify.js";

    // name of beautifier function
    private static final String BEAUTIFY_METHOD_NAME = "js_beautify";

    private final ScriptEngine engine;

    JavascriptBeautifierForJava() throws ScriptException {
        engine = new ScriptEngineManager().getEngineByName("nashorn");

        // this is needed to make self invoking function modules work
        // otherwise you won't be able to invoke your function
        engine.eval("var global = this;");
        engine.eval(new InputStreamReader(getClass().getClassLoader().getResourceAsStream(BEAUTIFY_JS_RESOURCE)));
    }

    public String beautify(String javascriptCode) throws ScriptException, NoSuchMethodException {
        return (String) ((Invocable) engine).invokeFunction(BEAUTIFY_METHOD_NAME, javascriptCode);
    }

    public static void main(String[] args) throws ScriptException, NoSuchMethodException {
        String unformattedJs = "var a = 1; b = 2; var user = { name : \n \"Andrew\"}";

        JavascriptBeautifierForJava javascriptBeautifierForJava = new JavascriptBeautifierForJava();
        String formattedJs = javascriptBeautifierForJava.beautify(unformattedJs);

        System.out.println(formattedJs);
        // will print out:
        //        var a = 1;
        //        b = 2;
        //        var user = {
        //            name: "Andrew"
        //        }
    }
}

If you're going to use this approach, make sure to reuse JavascriptBeautifier object, because it's not too effective to recreate one whenever you need to beautify code.

Roman Golyshev
  • 1,486
  • 15
  • 15
  • 1
    +1 for the perfect answer. One minor correction to the above code:- getClass().getClassLoader().getResourceAsStream(BEAUTIFY_JS_RESOURCE) – Abhishek K Apr 21 '18 at 07:11
  • Just if you have issue with latest beautifier js you can use older ones . I used 1.5.10 from here : https://cdnjs.com/libraries/js-beautify/1.5.10 – privatejava Apr 17 '20 at 21:35
3

Two closely-related questions (possible duplicates):

Community
  • 1
  • 1
N Rohler
  • 4,595
  • 24
  • 20
  • just be mindful that the "beautified" code is almost always bigger than the "minified" code. So I would suggest to "beautify" only on debug. – coolest_head Oct 24 '11 at 15:06
1

May be late - but still :)

There is a pretty printer sample in jdk9 repo. This uses Nashorn Parser API (https://docs.oracle.com/javase/9/docs/api/jdk/nashorn/api/tree/Parser.html)

http://hg.openjdk.java.net/jdk9/dev/nashorn/file/17cc754c8936/samples/prettyprinter.js

A. Sundararajan
  • 4,277
  • 1
  • 15
  • 30
0

The idea that comes to mind is manage your JavaScript output line by line (like a CodeLine class that has text and an indentation level) and when you're actually displaying this to the user and printing each line on a it's own line you can tab appropriately to format the code. It would require a custom class and probably something like an ArrayList<CodeLine>.

Brandon Buck
  • 7,177
  • 2
  • 30
  • 51
  • I have no longer control on how javascript is emitted (it is spread all over) – flybywire Oct 24 '11 at 15:13
  • @flybywire Then I failed to understand what you said you were doing in the code. I thought you mentioned you were generating the JavaScript with code, if that is the case then you alter the generation process with this method (or another one) otherwise, use a beautifier as suggested by N Rohler. – Brandon Buck Oct 24 '11 at 15:18
-2

use firefox with addon firebug. You can add breakpoints in your generated javascript and do some step by step debugging.

roel
  • 2,005
  • 3
  • 26
  • 41
  • @DaveNewton Formatting JS does not address the real issue of debugging how JS runs (which at least addresses half the OP's stated end goal). That is better done using a browser plug-in or browser functionality. – Andrew Thompson Oct 24 '11 at 17:55
  • 1
    @AndrewThompson Yep, agreed. But the question was, ultimately, about an easy way to format JS. – Dave Newton Oct 24 '11 at 18:15