Saturday, October 13, 2012

ACE Editor Syntax Checking Simple Mixed HTML

‹prev | My Chain | next›

Up today, I would like to see if I can get syntax checking working in the ACE editor. Actually, syntax checking is a built-in feature of ACE for certain modes. And it seems to work pretty well with JavaScript—except when JavaScript is embedded in an HTML document. Of course, all of the code in Gaming JavaScript is embedded inside HTML documents.

My initial strategy to get ACE to work with mixed HTML and JavaScript is to strip out the HTML, leaving behind only JavaScript. I cannot simply strip everything between HTML tags because <script> tags tend to live in between <html> and </html> tags.

Significantly complicating things is the need to retain the same number of lines. I cannot strip everything inside the <body> tag:
<body>
<h1>foo</h1>
<p>Bob went fishing while I slept.</p>
</body>
Because then I would be left with
<body></body>
Subsequent lines in the file would then have errors reported on the wrong line.

Instead of trying to solve all problems, I will start with the problems directly facing me in the book. The HTML in my templates looks simply like:
<body></body>
<script src="http://gamingJS.com/Three.js"></script>
<script src="http://gamingJS.com/ChromeFixes.js"></script>
<script>
  // This is where stuff in our game will happen:
  // ...
</script>
If all I need to do is remove empty <body> tags and <script> tags, well... I can do that.

After a bit of digging, I find that ACE has a JavaScript worker that is responsible for running JSHint against the code. Deep within that worker code is the line that gets the current value of the editor contents and parses it with JSHint:
oop.inherits(JavaScriptWorker, Mirror);

(function() {

    this.onUpdate = function() {
        var value = this.doc.getValue();
        value = value.replace(/^#!.*\n/, "\n");
        try {
            parser.parse(value);
        } catch(e) { /* ... */ }
    }
// ...
});
Interestingly, even though this is a JavaScript worker, it is replacing shebang lines. I can add on to that to replace my lines:
this.onUpdate = function() {
        var value = this.doc.getValue();
        value = value.replace(/^#!.*\n/, "\n");
        value = value.replace(/^<(\w+).*?>\s*<\/\1>/gm, "");
        value = value.replace(/<\/?script>/g, "");
        try {
            parser.parse(value);
        } catch(e) { /* ... */ }
   }
With my two replace() lines, I am replacing all lines with empty HTML pair tags with a newline. I am also stripping out <script> tags.

Thus, JSHint only sees the following when it parses my templates:
  // This is where stuff in our game will happen:
  // ...

As long as // ... is replaced with valid JavaScript, JSHint should see no errors or warnings.

And that seems to do the trick. If I add some intentionally broken code, I get warnings in the line number gutter of ACE. And if I mouse over them, then I am told what went wrong:


That is pretty darn nice. I might ask for simpler error messages that might help kids, but this is a start. If I can explain the most common error messages in the book and how to fix them, hopefully that will be good enough -- or at least no worse than having no warnings at all.



Day #538

2 comments:

  1. What file(s) does this code reside in?

    ReplyDelete
  2. The changes are all applied to ace/worker-javascript.js (the version used for the book is at: https://github.com/eee-c/ice-code-editor/blob/master/lib/js/ace/worker-javascript.js)

    ReplyDelete