JavaScript Language Injection in JSP

Answered

In IntelliJ, JSP files are considered as HTML content by default.

However, I have the situation that in our project some files contain JavaScript code, because these *.tag files are included from within a <script> block.

Now, I want the amazing code highlighting, suggestion, inspections, etc. of IntelliJ for this JavaScript code. I tried to trick the IDE to get what I want, but I did not quite succeed.

Example:
in javascript-init-main.tag I have

<script>
let bla = "This is recognized as JavaScript by IntelliJ and everything is working fine.";
let usingJsp1 = 'Mixing with ${"Java world"}.'
<mytaglib:javascript-init-sub.tag />
</script>

in javascript-init-sub.tag I have

let blub = "This is not recognized as JavaScript by IntelliJ because it is not placed inside a <script> tag"
let usingJsp2 = 'Mixing with ${"Java world"}'

Question: how to get proper JavaScript support in javascript-init-sub.tag?

I tried the following hack, to place a not-really-active script tag to trick the IDE

${"/*"}<script>${"*/"}
let blub = "This is now recognized as JavaScript by IntelliJ because it is assumed to be placed inside a <script> tag"
let usingJsp2 = 'Mixing with ${"Java world"}'
${"/*"}</script>${"*/"}

However, this does not work in the browser because </script> is terminating the original <script> tag from javascript-init-main.
But it would work when using something else than <script>.

I know about Language Injection and tried to introduce a <typescript> tag that should inject the language just as <script> does.
Therefor, I extended the built-in injection rule to "XML Tag: script|typescript". Then I tried:

${"/*"}<typescript>${"*/"}
let blub = "I did not find a way to make this work. Either JavaScript is not recognized, or mixing with JSP did not work."
let usingJsp2 = 'Mixing with ${"Java world"}'
${"/*"}</typescript>${"*/"}

Sadly, this trickery did not work. The mixing with JSP is broken when I do this. I guess IntelliJ has some custom logic for the script tag.

So I am back where I started.
How to tell IntelliJ, what is the primary language inside a *.tag file? Maybe there is some rule that I can apply to the whole file?

0
8 comments

Actually, I just noticed that my trickery *does* work.

I can just omit the closing fake-tag, because the opening fake-tag in the end is only a JavaScript comment and does not need a counterpart.
IntelliJ will assume all text after the fake-tag to be JavaScript. Problem solved.

So, in javascript-init-sub.tag it is now

${"/*"}<script>${"*/"}
let blub = "This is now recognized as JavaScript by IntelliJ because it is assumed to be placed inside a <script> tag. No closing tag for this fake-tag is required because it is only a JavaScript comment."
let usingJsp2 = 'Mixing with ${"Java world"}'

Still, it would be nice if IntelliJ (or the JSP standard) would allow to specify the primary language in a *.tag file somehow.

0

You can add javascript-init-sub.tag to a list of file name patterns associated with JavaScript file type in Settings | Editor | File Types - this particular file will be treated as a javascript file while other .tag files will still be considered HTML

0

When using Settings | Editor | File Types, then everything JSP in the file is highlighted as error (e.g. <% %>).
I still want JSP but the rest should be considered JavaScript, like when using <script> element.

0

You can specify the data language right in your JSP code with contentType (see https://stackoverflow.com/questions/48382179/what-is-the-content-type-of-a-jsp-file, for example), like

<%@ page contentType="text/javascript;charset=UTF-8" language="java" %>

let blub = "This is not recognized as JavaScript by IntelliJ because it is not placed inside a <script> tag";
let usingJsp2 = 'Mixing with ${"Java world"}'
0

Yes, this would be what I want.
Problem is that it is not allowed in a *.tag file and IntelliJ does not know (cannot know) where I include the tag file.

When I do

<%@page contentType = "text/javascript" %>

then I get "Tag should not be used in tag file", i.e., the <@page is not allowed.

When I do

<%@tag contentType="text/javascript"

then I get "Attribute contentType is not allowed here".

So, what I want does not seem to be possible with JSP features.

0

I just found out about Template Data Languages.

But this did not work (or I use it wrong). When I specify the path to one of my tag files and set the Template Data Language to "JavaScript", then it does not make a difference. I don't get the same IDE features like when I use a <script> element.

0

It doesn't work for JSP file type, the data language is detected from the contentType (if any)

Related ticket: https://youtrack.jetbrains.com/issue/IDEA-100191

0

I changed my workaround slightly such that the the fake script element does not appear in the generated output anymore:

<% if (false) { %> ${"/*"}<script>${"*/"} <% } %>

Note that you could also omit the /* and */ part because the script element is not printed to the output anyway:

<% if (false) { %> <script> <% } %>

This way, you could also add a fake closing script element:

<% if (false) { %> </script> <% } %>

This workaround works well for me in IntelliJ 2021.1.1.

0

Please sign in to leave a comment.