Skip to content

Commit

Permalink
Support Mobiledoc 0.3.2
Browse files Browse the repository at this point in the history
  • Loading branch information
YoranBrondsema committed Jul 16, 2019
1 parent e57e186 commit b4c48ab
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 12 deletions.
4 changes: 3 additions & 1 deletion lib/renderer-factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
} from './renderers/0-2';
import Renderer_0_3, {
MOBILEDOC_VERSION_0_3_0,
MOBILEDOC_VERSION_0_3_1
MOBILEDOC_VERSION_0_3_1,
MOBILEDOC_VERSION_0_3_2
} from './renderers/0-3';
import RENDER_TYPE from './utils/render-type';

Expand Down Expand Up @@ -89,6 +90,7 @@
return new Renderer_0_2(mobiledoc, this.options).render();
case MOBILEDOC_VERSION_0_3_0:
case MOBILEDOC_VERSION_0_3_1:
case MOBILEDOC_VERSION_0_3_2:
return new Renderer_0_3(mobiledoc, this.options).render();
default:
throw new Error(`Unexpected Mobiledoc version "${version}"`);
Expand Down
8 changes: 5 additions & 3 deletions lib/renderers/0-3.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@ import {

export const MOBILEDOC_VERSION_0_3_0 = '0.3.0';
export const MOBILEDOC_VERSION_0_3_1 = '0.3.1';
export const MOBILEDOC_VERSION = MOBILEDOC_VERSION_0_3_0;
export const MOBILEDOC_VERSION_0_3_2 = '0.3.2';

const IMAGE_SECTION_TAG_NAME = 'img';

function validateVersion(version) {
switch (version) {
case MOBILEDOC_VERSION_0_3_0:
case MOBILEDOC_VERSION_0_3_1:
case MOBILEDOC_VERSION_0_3_2:
return;
default:
throw new Error(`Unexpected Mobiledoc version "${version}"`);
Expand Down Expand Up @@ -374,14 +375,15 @@ export default class Renderer {
return rendered || createTextNode(this.dom, '');
}

renderMarkupSection([type, tagName, markers]) {
renderMarkupSection([type, tagName, markers, attributes = []]) {
tagName = tagName.toLowerCase();
if (!isValidSectionTagName(tagName, MARKUP_SECTION_TYPE)) {
return;
}

let attrsObj = reduceAttributes(attributes);
let renderer = this.sectionElementRendererFor(tagName);
let element = renderer(tagName, this.dom);
let element = renderer(tagName, this.dom, attrsObj);

this.renderMarkersOnElement(element, markers);
return element;
Expand Down
32 changes: 32 additions & 0 deletions lib/utils/array-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,35 @@ export function includes(array, detectValue) {
}
return false;
}


/**
* @param {Array} array of key1,value1,key2,value2,...
* @return {Object} {key1:value1, key2:value2, ...}
* @private
*/
export function kvArrayToObject(array) {
if (!Array.isArray(array)) { return {}; }

const obj = {};
for (let i = 0; i < array.length; i+=2) {
let [key, value] = [array[i], array[i+1]];
obj[key] = value;
}
return obj;
}

/**
* @param {Object} {key1:value1, key2:value2, ...}
* @return {Array} array of key1,value1,key2,value2,...
* @private
*/
export function objectToSortedKVArray(obj) {
const keys = Object.keys(obj).sort();
const result = [];
keys.forEach(k => {
result.push(k);
result.push(obj[k]);
});
return result;
}
22 changes: 21 additions & 1 deletion lib/utils/render-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,30 @@ import {
sanitizeHref
} from './sanitization-utils';

export function defaultSectionElementRenderer(tagName, dom) {
export const VALID_ATTRIBUTES = [
'data-md-text-align'
];

function _isValidAttribute(attr) {
return VALID_ATTRIBUTES.indexOf(attr) !== -1;
}

function handleMarkupSectionAttribute(element, attributeKey, attributeValue) {
if (!_isValidAttribute(attributeKey)) {
throw new Error(`Cannot use attribute: ${attributeKey}`);
}

element.setAttribute(attributeKey, attributeValue);
}

export function defaultSectionElementRenderer(tagName, dom, attrsObj = {}) {
let element;
if (isMarkupSectionElementName(tagName)) {
element = dom.createElement(tagName);

Object.keys(attrsObj).forEach(k => {
handleMarkupSectionAttribute(element, k, attrsObj[k]);
});
} else {
element = dom.createElement('div');
element.setAttribute('class', tagName);
Expand Down
18 changes: 11 additions & 7 deletions tests/helpers/create-mobiledoc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const MOBILEDOC_VERSION_0_3_1 = '0.3.1';
const MOBILEDOC_VERSION_0_3_2 = '0.3.2';
import {
MARKUP_SECTION_TYPE,
CARD_SECTION_TYPE
Expand All @@ -8,7 +8,9 @@ import {
ATOM_MARKER_TYPE
} from 'mobiledoc-dom-renderer/utils/marker-types';

export function createBlankMobiledoc({version=MOBILEDOC_VERSION_0_3_1}={}) {
import { objectToSortedKVArray } from 'mobiledoc-dom-renderer/utils/array-utils';

export function createBlankMobiledoc({version=MOBILEDOC_VERSION_0_3_2}={}) {
return {
version,
atoms: [],
Expand All @@ -18,7 +20,7 @@ export function createBlankMobiledoc({version=MOBILEDOC_VERSION_0_3_1}={}) {
};
}

export function createMobiledocWithAtom({version=MOBILEDOC_VERSION_0_3_1, atom}={}) {
export function createMobiledocWithAtom({version=MOBILEDOC_VERSION_0_3_2, atom}={}) {
return {
version,
atoms: [atom],
Expand All @@ -32,7 +34,7 @@ export function createMobiledocWithAtom({version=MOBILEDOC_VERSION_0_3_1, atom}=
};
}

export function createMobiledocWithCard({version=MOBILEDOC_VERSION_0_3_1, card}={}) {
export function createMobiledocWithCard({version=MOBILEDOC_VERSION_0_3_2, card}={}) {
return {
version,
atoms: [],
Expand All @@ -46,7 +48,7 @@ export function createMobiledocWithCard({version=MOBILEDOC_VERSION_0_3_1, card}=
};
}

export function createSimpleMobiledoc({sectionName='p', text='hello world', markup=null, version=MOBILEDOC_VERSION_0_3_1}={}) {
export function createSimpleMobiledoc({sectionName='p', text='hello world', markup=null, version=MOBILEDOC_VERSION_0_3_2, attributes={}}={}) {
let openedMarkups = markup ? [0] : [];
let closedMarkups = markup ? 1 : 0;
let markups = markup ? [markup] : [];
Expand All @@ -58,8 +60,10 @@ export function createSimpleMobiledoc({sectionName='p', text='hello world', mark
markups: markups,
sections: [
[MARKUP_SECTION_TYPE, sectionName, [
[MARKUP_MARKER_TYPE, openedMarkups, closedMarkups, text]]
]
[MARKUP_MARKER_TYPE, openedMarkups, closedMarkups, text]
],
objectToSortedKVArray(attributes)
],
]
};
}
31 changes: 31 additions & 0 deletions tests/unit/renderers/0-3-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
const { test, module } = QUnit;
const MOBILEDOC_VERSION_0_3_0 = '0.3.0';
const MOBILEDOC_VERSION_0_3_1 = '0.3.1';
const MOBILEDOC_VERSION_0_3_2 = '0.3.2';
const dataUri = "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=";


Expand Down Expand Up @@ -71,6 +72,36 @@ test('renders 0.3.0 markup section "pull-quote" as div with class', (assert) =>
assert.equal(outerHTML(sectionEl), '<div class="pull-quote">hello world</div>');
});

test('renders 0.3.2 markup section attributes', (assert) => {
let mobiledoc = createSimpleMobiledoc({
version: MOBILEDOC_VERSION_0_3_2,
sectionName: 'p',
text: 'hello world',
attributes: { 'data-md-text-align': 'center' }
});

let { result: rendered } = renderer.render(mobiledoc);
assert.equal(childNodesLength(rendered), 1,
'renders 1 section');
let sectionEl = rendered.firstChild;

assert.equal(outerHTML(sectionEl), '<p data-md-text-align="center">hello world</p>');
});

test('throws when given invalid attribute', (assert) => {
let mobiledoc = createSimpleMobiledoc({
version: MOBILEDOC_VERSION_0_3_2,
sectionName: 'p',
text: 'hello world',
attributes: { 'data-md-bad-attribute': 'something' }
});

assert.throws(
() => { renderer.render(mobiledoc) }, // jshint ignore: line
new RegExp(`Cannot use attribute: data-md-bad-attribute`)
);
});

test('renders 0.3.1 markup section "pull-quote" as div with class', (assert) => {
let mobiledoc = createSimpleMobiledoc({
version: MOBILEDOC_VERSION_0_3_1,
Expand Down
52 changes: 52 additions & 0 deletions tests/unit/utils/array-utils-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/* global QUnit */

import {
kvArrayToObject,
objectToSortedKVArray
} from 'mobiledoc-dom-renderer/utils/array-utils';

const { test, module } = QUnit;

module('Unit: Mobiledoc DOM Renderer - Array utils');

test('#kvArrayToObject', (assert) => {
assert.deepEqual(
kvArrayToObject([]),
{}
);
assert.deepEqual(
kvArrayToObject(['data-md-text-align', 'center']),
{
'data-md-text-align': 'center'
}
);
});

test('#objectToSortedKVArray', (assert) => {
assert.deepEqual(
objectToSortedKVArray({}),
[]
);
assert.deepEqual(
objectToSortedKVArray(
{
'data-md-text-align': 'center'
}
),
[
'data-md-text-align', 'center'
]
);
assert.deepEqual(
objectToSortedKVArray(
{
'data-md-text-align': 'center',
'data-md-color': 'red'
}
),
[
'data-md-color', 'red',
'data-md-text-align', 'center'
]
);
});

0 comments on commit b4c48ab

Please sign in to comment.