Introducing ember-prismic-dom

Ewan McDougall
The Qonto Way
Published in
5 min readMar 18, 2021
Prismic to Qonto to Display Article Image

Seamless integration of Prismic with Ember.js

We are happy to announce ember-prismic-dom, a new open source package that provides developers with easy Prismic rendering in Ember.js.

<Prismic::Dom @nodes={{@prismicData}} />

Prismic is a headless content management system used in numerous features and across multiple platforms at Qonto. It allows us to easily separate content creation from our application development workflow. For instance Prismic is used to manage frequently asked questions or FAQ’s, for mobile and web apps. It allows Product Managers to update FAQs without involving any developers. Thanks to Prismic they can be autonomous. A good example of how Prismic can be used is our web app which is written in Ember.js.

In this article we’ll look at simple usage of ember-prismic-dom, how it can replace prismic-dom, how ember-prismic-dom can be used to write custom elements using Ember.js template based rendering and how to leverage existing addons when writing custom elements.

Basic Usage

The initial pipeline to render the FAQ used Prismics library prismic-dom.

Diagram of prismic-dom HTML rendering pipeline: web app loads, fetch FAQ json flat, prismic-javascript, json tree / DOM like, prismic-dom, escaped HTML string, Ember.js, add HTML string to DOM unescaped, FAQ displayed.

The example below shows how FAQ data retrieved from prismic.io would be rendered using prismic-dom.

my-component.js:

import Component from '@glimmer/component';
import PrismicDOM from 'prismic-dom';
export default class MyComponent extends Component {
get html() {
return PrismicDOM.RichText.asHtml(this.args.myFaq);
}
}

my-component.hbs:

{{{this.html}}}

We wrote ember-prismic-dom to replace prismic-dom in our application. Using ember-prismic-dom, we can rewrite the previous example.

<Prismic::Dom @nodes={{@myFaq}} />

Motivation

We wanted to easily integrate Ember.js components and addons when rendering Prismic data. We also wanted to make auditing our code simpler.

Simpler code auditing

Ember.js is a template centric JavaScript framework which uses Handlebars.js as its default templating language. Handlebars.js escapes values returned by a ‘double-stash’ {{expression}}. To render an unescaped HTML string, in this instance the output of prismic-dom the 'triple-stash' is used {{{this.html}}}. Internally, prismic-dom will attempt to escape potentially dangerous input so that {{{this.html}}} is safe to use.

If we use prismic-dom we double the mechanisms in our app being used to escape possibly harmful content which could potentially lead to cross-site scripting vulnerabilities, XSS. Instead of relying on a single method, Handlebar.js, to correctly escape content, we are relying on Hanldebars.js and prismic-dom correctly escaping content which increases the risk of XSS.

Diagram of ember-prismic-dom HTML rendering pipeline: web app loads, fetch FAQ json flat, prismic-javascript, json tree / DOM like, ember-prismic-dom, add HTML string to DOM escaped, FAQ displayed.

Take this example

my-component.js:

export default class MyComponent extends Component {
get html () {
return `<img src="${element.url}">`;
}
}

my-component.hbs:

{{{this.html}}}

The {{{this.html}}} is unescaped. We are placing trust in element.url. If that comes from a third party, we are trusting their systems are secure, all content correctly escaped, and anybody with access to updating the image URL is trusted. If element.url='cats.png" onload=alert(document.cookie);"' when the image is loaded, an alert with the user’s cookie visible will pop up. Instead of alerting the user, the onload could send the cookie to the attacker, giving them access to the user’s account.

We have a high confidence that Ember.js protects us from XSS and want to rely on a single escape mechanism when rendering HTML. By writing ember-prismic-dom and removing the need for the 'triple-stash', we reduce the amount of code to audit, we only have to trust Ember.js to protect us against XSS.

Easily integrate custom components

The Ember.js template approach doesn’t integrate with prismic-dom. We cannot use custom components when rendering custom prismic elements with prismic-dom.

prismic-dom provides a mechanism to override element rendering for specific tags using a HTML Serializer function. For example custom element rendering of image and list tags:

my-component.js:

import Component from '@glimmer/component';
import PrismicDOM from 'prismic-dom';
export default class MyComponent extends Component {
get html () {
return PrismicDOM.RichText.asHtml(this.args.myFaq, this.args.linkResolver, this.htmlSerializer);
}
get htmlSerializer (type, element, content, children) {
switch(type) {
case Elements.list: return `<ul>${children.join('')}</ul>`;
case Elements.image: return `<img src="${element.url}">`;
default: return null;
}
}
}

my-component.hbs:

{{{this.html}}}

Replacing this with ember-prismic-dom is straightforward and allows for Ember.js template based HTML rendering.

<Prismic::Dom @nodes={{@nodes}} @image='image' @list='list'>

image.hbs:

<img src={{@node.element.url}}/>

list.hbs:

<ul>{{yield}}</ul>

More importantly it lets you leverage the existing ember-addon ecosystem. For example you want to use ember-async-image

image.hbs:

<AsyncImage src={{@node.element.url}}/>

Conclusion

In this article, we looked at rendering Prismic data using ember-prismic-dom and how it can be used to render custom elements and integrate with ember-addons. We also examined how it helps make code easier to audit. ember-prismic-dom allows us to write idiomatic Ember.js which results in a better developer experience. It makes merge requests to our codebase easier to review and our codebase more readable.

At Qonto we love using Prismic. It enables us to seperate content creation and management from software development. Creating ember-prismic-dom helps us secure, implement, review and ship features built on top of it. If you’re writing an app in Ember.js and are using Prismic I encourage you to try ember-prismic-dom.

About Qonto

Qonto is a neobank for SMEs and freelancers founded in 2016 by Steve Anavi and Alexandre Prot. Since the launch in July 2017, Qonto has made business banking easy for more than 150,000 companies. Thanks to Qonto, business owners save time (streamlined account opening before a day-to-day user experience with unlimited history, accounting exports, expense management feature), have more control while giving their teams autonomy (real-time notifications, user right management system) and have improved visibility on cash-flows (smart dashboards, transactions auto-tagging, and cash-flow monitoring). They also enjoy stellar customer support, at a fair and transparent price.

Interested in joining a challenging and game changer company? Consult our job offers!

--

--