From e6fd6fd2bf701b7697eed3fd0dd8078bd268931b Mon Sep 17 00:00:00 2001 From: Cory Forsyth Date: Wed, 18 Nov 2015 18:07:35 -0500 Subject: [PATCH] refactor to handle new cards fixes #17 --- README.md | 21 ++- lib/cards/image.js | 23 +-- lib/index.js | 9 +- lib/renderer-factory.js | 41 +++++ lib/renderer.js | 264 ++++++++++++++++++------------ lib/utils/dom.js | 8 + lib/utils/render-type.js | 1 + tests/unit/renderer-test.js | 313 ++++++++++++++++++++++++++---------- 8 files changed, 471 insertions(+), 209 deletions(-) create mode 100644 lib/renderer-factory.js create mode 100644 lib/utils/render-type.js diff --git a/README.md b/README.md index 1850c39..6f75955 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## Mobiledoc DOM Renderer [![Build Status](https://travis-ci.org/bustlelabs/mobiledoc-dom-renderer.svg?branch=master)](https://travis-ci.org/bustlelabs/mobiledoc-dom-renderer) -This is a DOM renderer for the [Mobiledoc](https://github.com/bustlelabs/content-kit-editor/blob/master/MOBILEDOC.md) format used +This is a DOM renderer for the [Mobiledoc](https://github.com/bustlelabs/mobiledoc-kit/blob/master/MOBILEDOC.md) format used by [Mobiledoc-Kit](https://github.com/bustlelabs/mobiledoc-kit). The renderer is a small library intended for use in browser clients. @@ -9,7 +9,7 @@ The renderer is a small library intended for use in browser clients. ``` var mobiledoc = { - version: "0.1", + version: "0.2.0", sections: [ [ // markers ['B'] @@ -26,14 +26,23 @@ var mobiledoc = { ] ] }; -var renderer = new MobiledocDOMRenderer(); -var cards = {}; -var rendered = renderer.render(mobiledoc, document.createElement('div'), cards); -document.getElementById('output').appendChild(rendered); +var renderer = new MobiledocDOMRenderer({cards: []}); +var rendered = renderer.render(mobiledoc); +var result = rendered.result; +document.getElementById('output').appendChild(result); // renders

hello world

// into 'output' element ``` +The Renderer constructor accepts a single object with the following optional properties: + * `cards`: An array of card objects + * `cardOptions`: Options to pass to cards when they are rendered + * `unknownCardHandler`: A method that will be called when any unknown card is enountered + +The return value from `renderer.render(mobiledoc)` is an object with two properties: + * `result` The rendered result. A DOMNode + * `teardown` A teardown method that, when called, will tear down the rendered mobiledoc and call any teardown handlers that were registered by cards in the mobiledoc. + ### Tests * `npm test` diff --git a/lib/cards/image.js b/lib/cards/image.js index e47b9ab..19502f7 100644 --- a/lib/cards/image.js +++ b/lib/cards/image.js @@ -1,19 +1,12 @@ -import { - createElement, - appendChild -} from '../utils/dom'; +import { createElement } from '../utils/dom'; +import RENDER_TYPE from '../utils/render-type'; -const ImageCard = { +export default { name: 'image', - display: { - setup(element, options, env, payload) { - if (payload.src) { - let img = createElement('img'); - img.src = payload.src; - appendChild(element, img); - } - } + type: RENDER_TYPE, + render({payload}) { + let img = createElement('img'); + img.src = payload.src; + return img; } }; - -export default ImageCard; diff --git a/lib/index.js b/lib/index.js index 0ea3cd4..f48b3bf 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,7 +1,10 @@ -import Renderer from './renderer'; +import RendererFactory from './renderer-factory'; +import RENDER_TYPE from './utils/render-type'; + +export { RENDER_TYPE }; export function registerGlobal(window) { - window.MobiledocDOMRenderer = Renderer; + window.MobiledocDOMRenderer = RendererFactory; } -export default Renderer; +export default RendererFactory; diff --git a/lib/renderer-factory.js b/lib/renderer-factory.js new file mode 100644 index 0000000..886a626 --- /dev/null +++ b/lib/renderer-factory.js @@ -0,0 +1,41 @@ +import Renderer from './renderer'; +import RENDER_TYPE from './utils/render-type'; + +/** + * runtime DOM renderer + * renders a mobiledoc to DOM + * + * input: mobiledoc + * output: DOM + */ + +function validateCards(cards) { + if (!Array.isArray(cards)) { + throw new Error('`cards` must be passed as an array, not an object.'); + } + + for (let i=0; i < cards.length; i++) { + let card = cards[i]; + if (card.type !== RENDER_TYPE) { + throw new Error(`Card "${card.name}" must be of type "${RENDER_TYPE}", is type "${card.type}"`); + } + if (!card.render) { + throw new Error(`Card "${card.name}" must define \`render\``); + } + } +} + +export default class RendererFactory { + constructor({cards, atoms, cardOptions, unknownCardHandler}={}) { + cards = cards || []; + validateCards(cards); + atoms = atoms || []; + cardOptions = cardOptions || {}; + + this.state = { cards, atoms, cardOptions, unknownCardHandler }; + } + + render(mobiledoc) { + return new Renderer(mobiledoc, this.state).render(); + } +} diff --git a/lib/renderer.js b/lib/renderer.js index d0d66ba..68239f5 100644 --- a/lib/renderer.js +++ b/lib/renderer.js @@ -1,24 +1,19 @@ import { createElement, appendChild, + removeChild, createTextNode, - setAttribute + setAttribute, + createDocumentFragment } from './utils/dom'; import ImageCard from './cards/image'; +import RENDER_TYPE from './utils/render-type'; const MARKUP_SECTION_TYPE = 1; const IMAGE_SECTION_TYPE = 2; const LIST_SECTION_TYPE = 3; const CARD_SECTION_TYPE = 10; -/** - * runtime DOM renderer - * renders a mobiledoc to DOM - * - * input: mobiledoc - * output: DOM - */ - function createElementFromMarkerType([tagName, attributes]=['', []]){ let element = createElement(tagName); attributes = attributes || []; @@ -31,118 +26,189 @@ function createElementFromMarkerType([tagName, attributes]=['', []]){ return element; } -function renderMarkersOnElement(element, markers, renderState) { - let elements = [element]; - let currentElement = element; +function validateVersion(version) { + if (version !== '0.2.0') { + throw new Error(`Unexpected Mobiledoc version "${version}"`); + } +} + +export default class Renderer { + constructor(mobiledoc, state) { + let { cards, cardOptions, atoms, unknownCardHandler } = state; + let { version, sections: sectionData } = mobiledoc; + validateVersion(version); + + const [markerTypes, sections] = sectionData; + + this.root = createDocumentFragment(); + this.markerTypes = markerTypes; + this.sections = sections; + this.cards = cards; + this.atoms = atoms; + this.cardOptions = cardOptions; + this.unknownCardHandler = unknownCardHandler || this._defaultUnknownCardHandler; + + this._teardownCallbacks = []; + this._renderedChildNodes = []; + } + + get _defaultUnknownCardHandler() { + return ({env: {name}}) => { + throw new Error(`Card "${name}" not found but no unknownCardHandler was registered`); + }; + } + + render() { + this.sections.forEach(section => { + appendChild(this.root, this.renderSection(section)); + }); + // maintain a reference to child nodes so they can be cleaned up later by teardown + this._renderedChildNodes = Array.prototype.slice.call(this.root.childNodes); + return { result: this.root, teardown: () => this.teardown() }; + } - for (let i=0, l=markers.length; i { - appendChild(element, (renderListItem(li, renderState))); - }); - return element; -} + renderListSection([type, tagName, listItems]) { + const element = createElement(tagName); + listItems.forEach(li => { + appendChild(element, (this.renderListItem(li))); + }); + return element; + } -function renderImageSection([type, src]) { - let element = createElement('img'); - element.src = src; - return element; -} + renderImageSection([type, src]) { + let element = createElement('img'); + element.src = src; + return element; + } -function renderCardSection([type, name, payload], renderState) { - let { cards } = renderState; - let card = cards[name]; - if (!card) { - throw new Error(`Cannot render unknown card named ${name}`); + findCard(name) { + for (let i=0; i < this.cards.length; i++) { + if (this.cards[i].name === name) { + return this.cards[i]; + } + } + if (name === ImageCard.name) { + return ImageCard; + } + return this._createUnknownCard(name); } - if (!payload) { - payload = {}; + + _createUnknownCard(name) { + return { + name, + type: RENDER_TYPE, + render: this.unknownCardHandler + }; } - let element = createElement('div'); - let cardOptions = renderState.options.cardOptions || {}; - card.display.setup(element, cardOptions, {name}, payload); - return element; -} -function renderMarkupSection([type, tagName, markers], renderState) { - const element = createElement(tagName); - renderMarkersOnElement(element, markers, renderState); - return element; -} + _createCardArgument(card, payload={}) { + let env = { + name: card.name, + isInEditor: false, + onTeardown: (callback) => this._registerTeardownCallback(callback) + }; -function renderSection(section, renderState) { - const [type] = section; - switch (type) { - case MARKUP_SECTION_TYPE: - return renderMarkupSection(section, renderState); - case IMAGE_SECTION_TYPE: - return renderImageSection(section, renderState); - case LIST_SECTION_TYPE: - return renderListSection(section, renderState); - case CARD_SECTION_TYPE: - return renderCardSection(section, renderState); - default: - throw new Error('Unimplement renderer for type ' + type); + let options = this.cardOptions; + + return { env, options, payload }; } -} -function validateVersion(version) { - if (version !== '0.2.0') { - throw new Error(`Unexpected Mobiledoc version "${version}"`); + _registerTeardownCallback(callback) { + this._teardownCallbacks.push(callback); } -} -export default class Renderer { - /** - * @param {Mobiledoc} mobiledoc - * @param {DOMNode} [rootElement] defaults to an empty div - * @param {Object} [cards] Each top-level property on the object is considered - * to be a card's name, its value is an object with `setup` and (optional) `teardown` - * properties - * @return DOMNode - */ - render({version, sections: sectionData}, root=createElement('div'), cards={}, options={}) { - validateVersion(version); - const [markerTypes, sections] = sectionData; - cards.image = cards.image || ImageCard; - const renderState = {root, markerTypes, cards, options}; + renderCardSection([type, name, payload]) { + let card = this.findCard(name); + + let cardWrapper = this._createCardElement(); + let cardArg = this._createCardArgument(card, payload); + let rendered = card.render(cardArg); + + this._validateCardRender(rendered, card.name); + + if (rendered) { + appendChild(cardWrapper, rendered); + } + return cardWrapper; + } + + _createCardElement() { + return createElement('div'); + } - if (Array.isArray(cards)) { - throw new Error('`cards` must be passed as an object, not an array.'); + _validateCardRender(rendered, cardName) { + if (!rendered) { + return; } - sections.forEach(section => { - let rendered = renderSection(section, renderState); - appendChild(renderState.root, rendered); - }); + if (typeof rendered !== 'object') { + throw new Error(`Card "${cardName}" must render ${RENDER_TYPE}, but result was "${rendered}"`); + } + } - return root; + renderMarkupSection([type, tagName, markers]) { + const element = createElement(tagName); + this.renderMarkersOnElement(element, markers); + return element; } } + diff --git a/lib/utils/dom.js b/lib/utils/dom.js index 2cfbac5..4f1cb74 100644 --- a/lib/utils/dom.js +++ b/lib/utils/dom.js @@ -6,6 +6,10 @@ export function appendChild(target, child) { target.appendChild(child); } +export function removeChild(target, child) { + target.removeChild(child); +} + function addHTMLSpaces(text) { let nbsp = '\u00A0'; return text.replace(/ /g, ' ' + nbsp); @@ -18,3 +22,7 @@ export function createTextNode(text) { export function setAttribute(node, propName, value) { node.setAttribute(propName, value); } + +export function createDocumentFragment() { + return document.createDocumentFragment(); +} diff --git a/lib/utils/render-type.js b/lib/utils/render-type.js new file mode 100644 index 0000000..91fc666 --- /dev/null +++ b/lib/utils/render-type.js @@ -0,0 +1 @@ +export default 'dom'; diff --git a/tests/unit/renderer-test.js b/tests/unit/renderer-test.js index 59893ab..2cf2f3b 100644 --- a/tests/unit/renderer-test.js +++ b/tests/unit/renderer-test.js @@ -1,22 +1,160 @@ /* global QUnit */ -const { test } = QUnit; +const { test, module } = QUnit; const MOBILEDOC_VERSION = '0.2.0'; import Renderer from 'mobiledoc-dom-renderer'; +import { RENDER_TYPE } from 'mobiledoc-dom-renderer'; + +const dataUri = "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs="; let renderer; -QUnit.module('Unit: Mobiledoc DOM Renderer', { +module('Unit: Mobiledoc DOM Renderer', { beforeEach() { renderer = new Renderer(); + }, + afterEach() { + if (renderer) { + renderer = null; + } } }); +test('rendering unknown card without unknownCardHandler throws', (assert) => { + let cardName = 'not-known'; + let mobiledoc = { + version: MOBILEDOC_VERSION, + sections: [ + [], + [ + [10, cardName] + ] + ] + }; + renderer = new Renderer({cards: [], unknownCardHandler: undefined}); + assert.throws( + () => renderer.render(mobiledoc), + new RegExp(`Card "${cardName}" not found.*no unknownCardHandler`) + ); +}); + +test('rendering unknown card uses unknownCardHandler', (assert) => { + assert.expect(5); + + let cardName = 'my-card'; + let expectedOptions = {}; + let expectedPayload = {}; + + let unknownCardHandler = ({env, options, payload}) => { + assert.equal(env.name, cardName, 'name is correct'); + assert.ok(!env.isInEditor, 'not in editor'); + assert.ok(!!env.onTeardown, 'has onTeardown'); + + assert.deepEqual(options, expectedOptions, 'correct options'); + assert.deepEqual(payload, expectedPayload, 'correct payload'); + }; + + let mobiledoc = { + version: MOBILEDOC_VERSION, + sections: [ + [], + [ + [10, cardName, expectedPayload] + ] + ] + }; + renderer = new Renderer({ + cards: [], cardOptions: expectedOptions, unknownCardHandler + }); + renderer.render(mobiledoc); +}); + +test('throws if card render returns invalid result', (assert) => { + let card = { + name: 'bad', + type: 'dom', + render() { return 'string'; } + }; + let mobiledoc = { + version: MOBILEDOC_VERSION, + sections: [ + [], + [ + [10, card.name] + ] + ] + }; + + renderer = new Renderer({cards:[card]}); + assert.throws( + () => renderer.render(mobiledoc), + /Card "bad" must render dom/ + ); +}); + +test('card may render nothing', (assert) => { + let card = { + name: 'ok', + type: 'dom', + render() {} + }; + let mobiledoc = { + version: MOBILEDOC_VERSION, + sections: [ + [], + [ + [10, card.name] + ] + ] + }; + + renderer = new Renderer({cards:[card]}); + renderer.render(mobiledoc); + + assert.ok(true, 'No error thrown'); +}); + test('it exists', (assert) => { assert.ok(Renderer, 'class exists'); assert.ok(renderer, 'instance exists'); }); +test('throws if given a card with an invalid type', (assert) => { + let cardName = 'bad'; + let card = { + name: cardName, + type: 'text', + render() {} + }; + let cards = [card]; + assert.throws( + () => { new Renderer({cards}) }, // jshint ignore: line + new RegExp(`Card "${cardName}" must be of type "${RENDER_TYPE}"`) + ); +}); + +test('throws if given a card without a render method', (assert) => { + let cardName = 'bad'; + let card = { + name: cardName, + type: RENDER_TYPE, + render: undefined + }; + let cards = [card]; + assert.throws( + () => { new Renderer({cards}) }, // jshint ignore: line + new RegExp(`Card "${cardName}" must define \`render\``) + ); +}); + +test('throws if given an object of cards', (assert) => { + let cards = {}; + assert.throws( + () => { new Renderer({cards}) }, // jshint ignore: line + new RegExp('`cards` must be passed as an array') + ); +}); + test('renders an empty mobiledoc', (assert) => { let mobiledoc = { version: MOBILEDOC_VERSION, @@ -25,11 +163,10 @@ test('renders an empty mobiledoc', (assert) => { [] // sections ] }; - let rendered = renderer.render(mobiledoc); + let { result: rendered } = renderer.render(mobiledoc); - assert.ok(rendered, 'renders output'); - assert.equal(rendered.childNodes.length, 0, - 'has no sections'); + assert.ok(!!rendered, 'renders result'); + assert.equal(rendered.childNodes.length, 0, 'has no sections'); }); test('renders a mobiledoc without markers', (assert) => { @@ -44,7 +181,8 @@ test('renders a mobiledoc without markers', (assert) => { ] ] }; - let rendered = renderer.render(mobiledoc); + let renderResult = renderer.render(mobiledoc); + let { result: rendered } = renderResult; assert.equal(rendered.childNodes.length, 1, 'renders 1 section'); assert.equal(rendered.childNodes[0].tagName, 'P', @@ -67,7 +205,7 @@ test('renders a mobiledoc with simple (no attributes) marker', (assert) => { ] ] }; - let rendered = renderer.render(mobiledoc); + let { result: rendered } = renderer.render(mobiledoc); assert.equal(rendered.childNodes.length, 1, 'renders 1 section'); let sectionEl = rendered.childNodes[0]; @@ -89,7 +227,7 @@ test('renders a mobiledoc with complex (has attributes) marker', (assert) => { ] ] }; - let rendered = renderer.render(mobiledoc); + let { result: rendered } = renderer.render(mobiledoc); assert.equal(rendered.childNodes.length, 1, 'renders 1 section'); let sectionEl = rendered.childNodes[0]; @@ -115,7 +253,7 @@ test('renders a mobiledoc with multiple markups in a section', (assert) => { ] ] }; - let rendered = renderer.render(mobiledoc); + let { result: rendered } = renderer.render(mobiledoc); assert.equal(rendered.childNodes.length, 1, 'renders 1 section'); let sectionEl = rendered.childNodes[0]; @@ -124,42 +262,41 @@ test('renders a mobiledoc with multiple markups in a section', (assert) => { }); test('renders a mobiledoc with image section', (assert) => { - let url = "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs="; let mobiledoc = { version: MOBILEDOC_VERSION, sections: [ [], // markers [ // sections - [2, url] + [2, dataUri] ] ] }; - let rendered = renderer.render(mobiledoc); + let { result: rendered } = renderer.render(mobiledoc); assert.equal(rendered.childNodes.length, 1, 'renders 1 section'); let sectionEl = rendered.childNodes[0]; - assert.equal(sectionEl.src, url); + assert.equal(sectionEl.src, dataUri); }); test('renders a mobiledoc with card section', (assert) => { - assert.expect(4); + assert.expect(7); let cardName = 'title-card'; - let payload = { - name: 'bob' - }; - let options = { - cardOptions: {foo: 'bar'} - }; - let expectedOptions = options.cardOptions; + let expectedPayload = { name: 'bob' }; + let expectedOptions = {foo: 'bar'}; let TitleCard = { name: cardName, - display: { - setup(element, options, env, setupPayload) { - assert.deepEqual(payload, setupPayload); - assert.deepEqual(options, expectedOptions); - element.innerHTML = setupPayload.name; - } + type: 'dom', + render({env, options, payload}) { + let {name, isInEditor, onTeardown} = env; + assert.equal(name, cardName, 'has name'); + assert.ok(!isInEditor, 'not isInEditor'); + assert.ok(!!onTeardown, 'has onTeardown'); + + assert.deepEqual(options, expectedOptions); + assert.deepEqual(payload, expectedPayload); + + return document.createTextNode(payload.name); } }; let mobiledoc = { @@ -167,74 +304,81 @@ test('renders a mobiledoc with card section', (assert) => { sections: [ [], // markers [ // sections - [10, cardName, payload] + [10, cardName, expectedPayload] ] ] }; - let cards = { - [cardName]: TitleCard - }; - let element = document.createElement('div'); - let rendered = renderer.render(mobiledoc, element, cards, options); - assert.equal(rendered.childNodes.length, 1, - 'renders 1 section'); + renderer = new Renderer({cards: [TitleCard], cardOptions: expectedOptions}); + let { result: rendered } = renderer.render(mobiledoc); + assert.equal(rendered.childNodes.length, 1, 'renders 1 section'); let sectionEl = rendered.childNodes[0]; - assert.equal(sectionEl.innerHTML, payload.name); + assert.equal(sectionEl.innerHTML, expectedPayload.name); }); -test('renders a mobiledoc with card section and no payload', (assert) => { - assert.expect(3); - let cardName = 'title-card'; - let TitleCard = { - name: cardName, - display: { - setup(element, options, env, setupPayload) { - assert.deepEqual({}, setupPayload); - element.innerHTML = ''; - } - } - }; +test('renderResult.teardown removes rendered sections from dom', (assert) => { let mobiledoc = { version: MOBILEDOC_VERSION, sections: [ - [], // markers - [ // sections - [10, cardName] + [], + [ + [1, 'p', [ + [[], 0, 'Hello world'] + ]] ] ] }; - let rendered = renderer.render(mobiledoc, document.createElement('div'), { - [cardName]: TitleCard - }); - assert.equal(rendered.childNodes.length, 1, - 'renders 1 section'); - let sectionEl = rendered.childNodes[0]; - assert.equal(sectionEl.innerHTML, ''); + let { result: rendered, teardown } = renderer.render(mobiledoc); + assert.equal(rendered.childNodes.length, 1, 'renders 1 section'); + + let fixture = document.getElementById('qunit-fixture'); + fixture.appendChild(rendered); + + assert.ok(fixture.childNodes.length === 1, 'precond - result is appended'); + + teardown(); + + assert.ok(fixture.childNodes.length === 0, 'rendered result removed after teardown'); }); -test('when passed an array of cards, throws', (assert) => { +test('card can register teardown hook', (assert) => { + let cardName = 'title-card'; + let didTeardown = false; + + let card = { + name: cardName, + type: 'dom', + render({env}) { + env.onTeardown(() => didTeardown = true); + } + }; + let mobiledoc = { version: MOBILEDOC_VERSION, sections: [ [], - [] + [ + [10, cardName] + ] ] }; - let cards = [{name: 'test-card'}]; - let element = document.createElement('div'); - assert.throws(() => { - renderer.render(mobiledoc, element, cards); - }, /cards.*must be passed as an object/); + renderer = new Renderer({cards: [card]}); + let { teardown } = renderer.render(mobiledoc); + + assert.ok(!didTeardown, 'teardown not called'); + + teardown(); + + assert.ok(didTeardown, 'teardown called'); }); -test('renders a mobiledoc with default image section', (assert) => { +test('renders a mobiledoc with default image card', (assert) => { assert.expect(3); let cardName = 'image'; let payload = { - src: 'http://example.org/foo.jpg' + src: dataUri }; let mobiledoc = { version: MOBILEDOC_VERSION, @@ -245,13 +389,13 @@ test('renders a mobiledoc with default image section', (assert) => { ] ] }; - let rendered = renderer.render(mobiledoc, document.createElement('div')); + let { result: rendered } = renderer.render(mobiledoc); assert.equal(rendered.childNodes.length, 1, 'renders 1 section'); let sectionEl = rendered.childNodes[0]; assert.equal(sectionEl.firstChild.tagName, 'IMG'); - assert.equal(sectionEl.firstChild.src, 'http://example.org/foo.jpg'); + assert.equal(sectionEl.firstChild.src, dataUri); }); test('renders mobiledoc with lists', (assert) => { @@ -267,7 +411,7 @@ test('renders mobiledoc with lists', (assert) => { ] ] }; - const rendered = renderer.render(mobiledoc, document.createElement('div')); + let { result: rendered } = renderer.render(mobiledoc, document.createElement('div')); assert.equal(rendered.childNodes.length, 1, 'renders 1 section'); const section = rendered.childNodes[0]; @@ -312,29 +456,26 @@ test('multiple spaces should preserve whitespace with nbsps', (assert) => { }; let nbsp = '\u00A0'; - let sn = ' ' + nbsp; + let sn = space + nbsp; let expectedText = [ repeat(sn, 2), 'some', - repeat(sn, 2), ' ', 'text', + repeat(sn, 2), space, 'text', repeat(sn, 3) ].join(''); - let rendered = renderer.render(mobiledoc); + let { result: rendered } = renderer.render(mobiledoc); let textNode = rendered.firstChild.firstChild; assert.equal(textNode.textContent, expectedText, 'renders the text'); }); test('rendering nested mobiledocs in cards', (assert) => { - let renderer = new Renderer(); - - let cards = { - 'nested-card': { - display: { - setup(element, options, env, payload) { - renderer.render(payload.mobiledoc, element, cards); - } - } + let cards = [{ + name: 'nested-card', + type: 'dom', + render({payload}) { + let {result: rendered} = renderer.render(payload.mobiledoc); + return rendered; } - }; + }]; let innerMobiledoc = { version: MOBILEDOC_VERSION, @@ -358,7 +499,8 @@ test('rendering nested mobiledocs in cards', (assert) => { ] }; - let rendered = renderer.render(mobiledoc, document.createElement('div'), cards); + let renderer = new Renderer({cards}); + let { result: rendered } = renderer.render(mobiledoc); assert.equal(rendered.childNodes.length, 1, 'renders 1 section'); let card = rendered.childNodes[0]; assert.equal(card.childNodes.length, 1, 'card has 1 child'); @@ -384,5 +526,4 @@ test('throw when given unexpected mobiledoc version', (assert) => { () => renderer.render(mobiledoc), /Unexpected Mobiledoc version.*0.2.1/ ); - });