Inject custom language into JS/CSS code

Answered

Is it possible to inject custom language into JS or CSS code? I developed plugin for custom language that can be used in HTML files this way:

Unfortunately, as you can see on the screenshot, custom language's parts are reported as errors when mixed with CSS/JS language. Is there any way to integrate this language with CSS/JS? Can custom language be injected into PsiLanguageInjectionHost types only?

12 comments
Comment actions Permalink

 

> Can custom language be injected into PsiLanguageInjectionHost types only?

Yes, languages can be injected in injection hosts only. Injections are not supposed to be used for creating custom template language support. I think you should use `com.intellij.psi.templateLanguages.TemplateLanguage` instead.

1
Comment actions Permalink

Thanks for your answer Alexander.

It's HTL (https://docs.adobe.com/docs/en/htl/overview.html) language which is like HTML extension. It can be used only in HTML files. It's very similar to Thymeleaf which is not implemented as TemplateLanguage in IntelliJ.

Is template language still more suitable here in your opinion? If yes, then why?

0
Comment actions Permalink

Hi Karol,

 

I think that template language is more suitable here, yes. Also, I've checked out the sources of Thymeleaf language and I doubt that it works good in CSS/JS. If it is, I can investigate how authors of Thymeleaf plugin reached this.

I'd say that it's worth to take a look at https://github.com/JetBrains/intellij-plugins/tree/master/handlebars plugin, it implements similar behavior on HTML files and as far as I know works fine on CSS/JS

1
Comment actions Permalink

I looked for plugin supporting something similar to HTL and (wrongly) decided to go with Thymeleaf approach.

Thanks for this link! If it works in HTML files, then it's perfect base to learn how to implement HTL plugin.

0
Comment actions Permalink

Hello Karol,

By a coincidence I'm implementing plugin for Sighlty (HTL) support too. I too utilize the PsiLanguageInjectionHost interface and don't have issues you've described:


The Sightly is recognized in every place.
Here is the list of interfaces I introspect in my "Injector" class:

override fun elementsToInjectIn(): MutableList<out Class<out PsiElement>> {
return listOf(
XmlText::class.java,
XmlAttributeValue::class.java,
XmlComment::class.java
).toMutableList()
}


Though, I have a problem in following cases:

The reason why these do not work is in following - the PsiElements in the beginning and in the ending of html file do not implement the PsiLanguageInjectionHost interface.

So, my question would be, how aforementioned cases should be handled? 


1
Comment actions Permalink

@Alexander Zolotov, the reason why the "handlebars" approach doesn't seem to be convenient: the Sightly doesn't have it's own extension, it lives in html files. So, in order to make a new template language we will have to override standard "html features". It seems as a huge overkill while everything works almost fine with "injection" approach.
I imagine following solution as the best for issue I"ve described in previous comment: I do substitute the PsiElements which my custom elements which are direct ancestors of problematic ones and simply implement PsiLanguageInjectionHost interface.
In that case the solution made so far will just start working while the existing IDEA's features will remain.

0
Comment actions Permalink

Hi Dmytro,
Please notice, that my screenshot is from IntelliJ IDEA Ultimate (you can see highlighted JS/CSS keywords) and your is from Community Edition (I guess). Community Edition doesn't support JavaScript and CSS and that's why you don't get parsing errors in script and style fragments. If you run your plugin in Ultimate, you will get the same errors as me.
Like Alexander said template language is more suitable solution here. I'm not sure what you mean by overriding standard HTML features. All you need to do is to "parse out" HTML fragments (left it for HTML language support provided by IntelliJ platform) and parse HTL fragments into HTL tokens. HTML will be handled by platform and you don't have to do anything additional with it. You just have to implement file view provider (to define template and data language) and language substitutor (to open *.html files as HTL templates). Handlebars plugin is great reference to base on.

0
Comment actions Permalink

Hi Karol,
Indeed, I've tested my plugin against the Community version of IDEA,
Thanks for your answer, I will check the Handlebars plugin

0
Comment actions Permalink

Hi guys,

I just want to confirm that Karol is completely right. Reimplementing HTML features is not needed, the only thing you have to implement is language substitutor. For example, Handlebars and Django template language support are implemented in this way.

0
Comment actions Permalink

Hi guys,

Been trying to implement "template language" approach, no progress though.
Could you please explain what the "Language substitution" mean?
The difference between "Template" language and an ordinary language?
The purpose of TemplateDataElementType class?
What should the templateElementType parameter contain?
What should the outerElementType parameter contain?

I've tried to reproduce the approach from handlebars plugin with mine.
The result is following:

Html part is totally absent, could you suggest what reasons of that might be?

0
Comment actions Permalink

Karol, in one of your previous comments you've told that not sightly elements should be "parsed out", could you please tell more on that?

0
Comment actions Permalink

Hi Dmytro,
I'm developing HTL/Sightly plugin (for entire AEM actually) and have working and released version already. I don't know what is your goal in developing it (learning/fun/work), but if you are interested in joining this project please contact me at karol86@gmail.com. I think that it doesn't make sense to develop competing plugins if we can join working resources. If not, let me know here - I'll answer your questions when I have more time (after Christmas or New Year).

0

Please sign in to leave a comment.