Search code examples
phpstormdrupal-8

Is there a way to use multiple languages in a single PhpStorm file?


So I have a potentially new use case. I'm trying to adopt a Single-File-Component method of creating code and templates for Drupal 8 content. There is a great Drupal module which facilities this (https://www.drupal.org/project/sfc), but I'd like to improve the code hinting and syntax highlighting for these files in PhpStorm 2020.1.

I have to use the .sfc extension. I added this extension to the PHP file type and for the most part, everything works as expected. The file starts out as XHTML and then there is a PHP section. Both HTML/XHTML and PHP are correctly highlighted and hinted. The .sfc file also contains JavaScript and CSS and both of those sections are also correctly highlighted and hinted, presumably because they are handled by PhpStorm's XHTML or PHP recognition.

The files looks something like this:

<template>
  <article class="test-class">
    <h2>Test content</h2>
    <p>This is some test content.</p>
  </article>
</template>

<style>
  .test-class {
    background-color: red;
  }
</style>

<script data-type="attach">
  console.log('JavaScript attached');
</script>

<?php
$definition = [
  'overrides' => [
    'node__article__teaser',
  ],
];

There is a lot more to the SFC modules` capabilities and this is a very basic template. By the way, the <template> tag is used to extract the Twig template out of the the PHP/XHTML document. That tag is not in the final result.

The <style> and <script> tags are what presumably triggers recognition of JavaScript and CSS. My problems start when I want to use SCSS and Twig instead of CSS and XHTML. Something like this:

<template>
  <article {{ attributes.addClass('test-class') }}>
    {{ content.title }}
    {{ content.body }}
  </article>
</template>

<style>
  .test-class {
    background-color: red;
    p:last-child {
      margin-bottom: 0;
    }
  }
</style>

<script data-type="attach">
  console.log('JavaScript attached');
</script>

<?php
$definition = [
  'overrides' => [
    'node__article__teaser',
  ],
];

I of course don't get proper highlighting/hinting/tabbing for the Twig or SCSS code blocks. I tried various versions of language injection, but they didn't seem to work either. Things like:

<template>
  <!-- language=twig -->
  ...
</template>
<style>
  /** language=scss **/
  ...
</style>

I'm assuming I need to create some sort of new language injection configuration for SCSS and Twig inside of a PHP file, but I can't find good documentation on how to do that.

Any suggestions?


Solution

  • SCSS -- Yes, Twig -- Nope.

    Twig:

    Not possible as is not an injectable language, it's a templating language that can only be used as a 'master' language for other languages. E.g. check comments here for Twig injectable into a PHP string: https://youtrack.jetbrains.com/issue/WI-38370).

    You may try Handlebars/Mustache instead (separate plugin): it has Twig-alike syntax so may cover at least some of the syntax (it is injectable).

    SCSS:

    Use <style type="text/scss"> so IDE can identify this one differently to standard plain CSS (available since 2017.1 version: https://stackoverflow.com/a/36331588/783119).

    In older versions (2016.3 and older) you would also need to create custom Language Injection rule, like this one:

    enter image description here