This addon renders Ember components embedded in mutable text content with an HTMLBars-like syntax. The primary use case is to provide an Ember-enabled markup language to untrusted users.
Suppose that userProvidedContent
is
Donald Trump and raccoons both
* have small hands and
* look like thieves.
{{youtube-video v='bQueaSlvjCw'}}
WhatBars allows safely rendering this content along with the Ember component:
We do not allow users to write raw HTML content in our websites for two reasons:
- Untrusted users may stage a cross-site scripting (XSS) attack.
- Even trusted users don't want to write HTML.
Addressing the first bullet point is as simple as sanitizing user input.
A popular solution for the second bullet point is to format user content with
Markdown. These methods are employeed right here in this README.md
.
Sanitizers and markup languages such as Markdown often limit our users more than we want. We can use plugins to add some functionality. For example, markdown-it-video provides a syntax for videos from popular sites. Integrating a markdown-it plugin with Ember (Data) may prove to be difficult, though.
If we trust our user content, we could run the HTMLBars template compiler on the client side:
import Ember from 'ember';
export default Ember.Component.extend({
layout: Ember.computed('template', function () {
return Ember.HTMLBars.compile(this.get('template'));
}),
});
However, this requires adding approximately a megabyte (~200k gzipped) to our
application's size by including ember-template-compiler.js
in
ember-cli-build.js
:
app.import('bower_components/ember/ember-template-compiler.js');
Plus, that method does not allow the templates to change after rendering them.
WhatBars allows untrusted content to use HTMLBars-like syntax to include
Ember components without requiring ember-template-compiler.js
.
The what-bars
component renders the enabled components that are embeded in
the provided content and runs the provided sanitizer on the rest of the
content. Only components that are explicitly enabled will be rendered,
and the sanitizer function must return an Ember.SafeString
.
For example, you might have a user-contribution component:
import Ember from 'ember';
import makeShinyAndSafe from 'whatever-you-want-to-use';
export default Ember.Component.extend({
classNames: ['user-contribution'],
enabled: ['youtube-video', 'jazz-hands-component'],
content: "",
sanitizer(contentFragment) {
const html = makeShinyAndSafe(contentFragment);
return Ember.String.htmlSafe(html);
}
});
Then simply use what-bars
in the user-contribution template:
Note that enabled
may be an array of component names, or an object with
component names as keys:
enabled: {'youtube-video': true, 'jazz-hands-component': true},
The makeShinyAndSafe
function could be something like:
import markdownit from 'markdown-it';
function makeShinyAndSafe(str) {
const md = markdownit({ /* markdown-it options here */ });
return md.render(str || "");
}
The named arguments are provided to the component as params
,
the positional arguments are provided as positional
, and
the block content is provided as block
.
(This could change when Ember gets
splat.)
A possible implementation of the youtube-video
component is:
import Ember from 'ember';
export default Ember.Component.extend({
classNames: ['youtube-video'],
params: {},
positional: [],
block: '',
v: Ember.computed('params', 'positional', function() {
return this.get('params').v || this.get('positional')[0];
}),
});
And the corresponding template might be:
This addon is under development and its interface may still change.
git clone https://github.com/w-hat/ember-whatbars
cd ember-whatbars
npm install
bower install
ember serve
- Visit your app at http://localhost:4200.
npm test
(Runsember try:each
to test your addon against multiple Ember versions)ember test
ember test --server
ember build
For more information on using ember-cli, visit https://ember-cli.com/.