152 lines
5.2 KiB
Markdown
152 lines
5.2 KiB
Markdown
|
## Mobiledoc DOM Renderer
|
||
|
|
||
|
This is a DOM renderer for the [Mobiledoc format](https://github.com/bustlelabs/mobiledoc-kit/blob/master/MOBILEDOC.md) used
|
||
|
by [Mobiledoc-Kit](https://github.com/bustlelabs/mobiledoc-kit).
|
||
|
|
||
|
To learn more about Mobiledoc cards and renderers, see the **[Mobiledoc Cards docs](https://github.com/bustlelabs/mobiledoc-kit/blob/master/CARDS.md)**.
|
||
|
|
||
|
The renderer is a small library intended for use in browser clients.
|
||
|
|
||
|
### Usage
|
||
|
|
||
|
```js
|
||
|
var mobiledoc = {
|
||
|
version: "0.3.0",
|
||
|
markups: ["B"],
|
||
|
atoms: [],
|
||
|
cards: [],
|
||
|
sections: [
|
||
|
[1, 'P', [ // array of markers
|
||
|
// marker
|
||
|
[ 0, // marker type 0 (standard text)
|
||
|
[0], // open markups (by index)
|
||
|
0, // close count
|
||
|
'hello world'
|
||
|
]
|
||
|
]
|
||
|
]
|
||
|
};
|
||
|
var renderer = new MobiledocDOMRenderer({cards: []});
|
||
|
var rendered = renderer.render(mobiledoc);
|
||
|
var result = rendered.result;
|
||
|
document.getElementById('output').appendChild(result);
|
||
|
// renders <div><p><b>hello world</b></b></div>
|
||
|
// into 'output' element
|
||
|
```
|
||
|
|
||
|
The Renderer constructor accepts a single object with the following optional properties:
|
||
|
|
||
|
* `cards` [array] - The list of card objects that the renderer may encounter in the mobiledoc
|
||
|
* `atoms` [array] - The list of atom objects that the renderer may encounter in the mobiledoc
|
||
|
* `cardOptions` [object] - Options to pass to cards and atoms when they are rendered
|
||
|
* `unknownCardHandler` [function] - Will be called when any unknown card is enountered
|
||
|
* `unknownAtomHandler` [function] - Will be called when any unknown atom is enountered
|
||
|
* `sectionElementRenderer` [object] - A map of hooks for section element rendering.
|
||
|
* Valid keys are P, H1, H2, H3, H4, H5, H6, BLOCKQUOTE, ASIDE
|
||
|
* Arguments are `tagName, dom`
|
||
|
* A valid value is a function that returns an element
|
||
|
* `markupElementRenderer` [object] - A map of hooks for inline element rendering.
|
||
|
* Valid keys are B, I, STRONG, EM, A, U, SUB, SUP, S, CODE
|
||
|
* Arguments are `tagName, dom, attributes={}`
|
||
|
* A valid value is a function that returns an element
|
||
|
* `dom` [object] - A native or [SimpleDOM](https://github.com/krisselden/simple-dom)
|
||
|
implementation of the DOM.
|
||
|
|
||
|
The return value from `renderer.render(mobiledoc)` is an object with two properties:
|
||
|
* `result` [DOM Node] - The rendered result
|
||
|
* `teardown` [function] - When called, this function will tear down the rendered mobiledoc and call any teardown handlers that were registered by cards when they were rendered
|
||
|
|
||
|
#### Rendering HTML
|
||
|
|
||
|
In a browser, rendering to HTML is simple:
|
||
|
|
||
|
```js
|
||
|
var renderer = new MobiledocDOMRenderer();
|
||
|
var rendered = renderer.render(mobiledoc);
|
||
|
var html = rendered.result.outerHTML;
|
||
|
```
|
||
|
|
||
|
However on the server in Node.js, native DOM APIs are not available. To make
|
||
|
server-rendering easy, this DOM
|
||
|
renderer is [SimpleDOM](https://github.com/krisselden/simple-dom)
|
||
|
compatible. You may pass an instance of a SimpleDOM document and serialize
|
||
|
its output. For example:
|
||
|
|
||
|
```js
|
||
|
var renderer = new MobiledocDOMRenderer({
|
||
|
dom: new SimpleDOM.Document()
|
||
|
});
|
||
|
var rendered = renderer.render(mobiledoc);
|
||
|
var serializer = new SimpleDOM.HTMLSerializer([]);
|
||
|
var html = serializer.serializeChildren(rendered.result);
|
||
|
```
|
||
|
|
||
|
This usage of the DOM renderer for rendering HTML has the advantage of allowing
|
||
|
developers to easily implement cards that work in a server and client context.
|
||
|
|
||
|
#### sectionElementRenderer
|
||
|
|
||
|
Use this renderer option to customize what element is used when rendering
|
||
|
a section.
|
||
|
|
||
|
```
|
||
|
var renderer = new MobiledocDOMRenderer({
|
||
|
sectionElementRenderer: {
|
||
|
P: function(_, dom) { return dom.createElement('span'); },
|
||
|
H1: function(_, dom) { return dom.createElement('h2'); },
|
||
|
H2: function(tagName, dom) {
|
||
|
var element = dom.createElement(tagName);
|
||
|
element.setAttribute('class', 'subheadline');
|
||
|
return element;
|
||
|
}
|
||
|
/* Valid keys are P, H1, H2, H3, H4, H5, H6, BLOCKQUOTE, ASIDE */
|
||
|
}
|
||
|
});
|
||
|
var rendered = renderer.render(mobiledoc);
|
||
|
```
|
||
|
|
||
|
#### markupElementRenderer
|
||
|
|
||
|
Use this renderer option to customize what inline tags are used when rendering
|
||
|
a section's content.
|
||
|
|
||
|
```
|
||
|
var renderer = new MobiledocDOMRenderer({
|
||
|
markupElementRenderer: {
|
||
|
B: function(_, dom) { return dom.createElement('strong'); },
|
||
|
A: function(tagName, dom, attrs={}) {
|
||
|
let element = dom.createElement(tagName);
|
||
|
|
||
|
for (let attr in attrs) {
|
||
|
element.setAttribute(attr, attrs[attr]);
|
||
|
}
|
||
|
|
||
|
element.setAttribute('rel', 'nofollow');
|
||
|
return element;
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
var rendered = renderer.render(mobiledoc);
|
||
|
```
|
||
|
|
||
|
#### Attribute Sanitization (XSS Protection)
|
||
|
|
||
|
Mobiledoc DOM Renderer sanitizes the `href` attribute of 'A' markups, prefixing
|
||
|
the string `unsafe:` on potentially unsafe urls. It determines an environment-
|
||
|
appropriate URL protocol parser. In rare cases it may be unable to determine one
|
||
|
(this can happen when running the renderer in a Node VM Sandbox, like ember-cli-
|
||
|
fastboot does), and will throw in that case. To fix this, you can provide a
|
||
|
custom markupElementRenderer for the 'A' tag that will be used instead of the
|
||
|
default.
|
||
|
|
||
|
### Tests
|
||
|
|
||
|
* To run tests via testem: `npm test`
|
||
|
* To run tests in the browser: `npm start` and open http://localhost:4200/tests
|
||
|
|
||
|
### Releasing
|
||
|
|
||
|
* Use `np` (install with `npm install -g np`)
|
||
|
* `np <version>` (e.g. `np 0.5.2`)
|
||
|
* `git push --tags`
|