Scala.js use ES6 tagged templates

On js there are libraries that rely on tagged templates to split static and dynamic sections of expresions, some examples

lit web components

import {LitElement, css, html} from 'lit';
import {customElement, property} from 'lit/decorators.js';

@customElement('simple-greeting')
export class SimpleGreeting extends LitElement {
  // Define scoped styles right with your component, in plain CSS
  static styles = css`
    :host {
      color: blue;
    }
  `;

  // Declare reactive properties
  @property()
  name?: string = 'World';

  // Render the UI as a function of component state
  render() {
    return html`<p>Hello, ${this.name}!</p>`;
  }
}

Emotion css

import { css } from '@emotion/css'

const color = 'white'
const classname = css`
    padding: 32px;
    background-color: hotpink;
    font-size: 24px;
    border-radius: 4px;
    &:hover {
      color: ${color};
    }
  `

is there a way to map those to scala.js bindings? so lit/emotion tagged templates can be used from scala.js

Tagged templates are syntactic sugar in JavaScript, like in Scala.

return html`<p>Hello, ${this.name}!</p>`;

desugars into

return html(["<p>Hello, ", "!</p>"], this.name);

Therefore, you can define html as a function taking a js.Array[String] and a varargs of Any*:

@js.native @JSGlobal("html")
def html(strings: js.Array[String], args: Any*): String = js.native

and call it as

html(js.Array("<p>Hello, ", "!</p>"), this.name)

With a bit more of effort, you can define html as a Scala string interpolator that will call the above method, so that you can then write

html"<p>Hello, ${this.name}!</p>"
2 Likes

Great stuff, indeed sounds like js tagged templates map to scala string interpolators