Skip to content

Commit

Permalink
Koenig - Versioned renderer (#9606)
Browse files Browse the repository at this point in the history
refs TryGhost/Ghost#9505
- updates mobiledoc converter's `render` method to accept a `version` argument
    - `1` === Ghost 1.0's markdown-only renderer output
    - `2` === Koenig's full mobiledoc renderer output
- switch between mobiledoc renderer versions in Post model's `onSaving` hook
    - version 1 by default
    - version 2 if Koenig is enabled (currently behind dev experiments config + labs flag)
    - version 2 if the post's mobiledoc is not compatible with the markdown-only renderer
- "version 2" full-Koenig mobiledoc renderer output
    - wraps content in a `.kg-post` div
    - removes wrapper around markdown and html card output
    - adds classes to image card output including selected image size/style
- standardises es6 usage across mobiledoc related files
  • Loading branch information
kevinansfield authored May 4, 2018
1 parent 5716c7d commit f6effeb
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 101 deletions.
2 changes: 2 additions & 0 deletions packages/kg-default-cards/lib/cards/hr.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict';

module.exports = {
name: 'hr',
type: 'dom',
Expand Down
14 changes: 1 addition & 13 deletions packages/kg-default-cards/lib/cards/html.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,8 @@ module.exports = {
name: 'html',
type: 'dom',
render(opts) {
let payload = opts.payload;
let dom = opts.env.dom;
let caption = '';

if (payload.caption) {
caption = `<p>${payload.caption}</p>`;
}

let html = `<div class="kg-card-html">${payload.html}${caption}</div>`;

// use the SimpleDOM document to create a raw HTML section.
// avoids parsing/rendering of potentially broken or unsupported HTML
let element = dom.createRawHTMLSection(html);

return element;
return opts.env.dom.createRawHTMLSection(opts.payload.html);
}
};
10 changes: 9 additions & 1 deletion packages/kg-default-cards/lib/cards/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,20 @@ module.exports = {
type: 'dom',
render(opts) {
let payload = opts.payload;
// let version = opts.options.version;
let dom = opts.env.dom;

let figure = dom.createElement('figure');
figure.setAttribute('class', 'kg-image-card');

let img = dom.createElement('img');
img.className = 'kg-card-image';
let imgClass = 'kg-image';
if (payload.imageStyle) {
imgClass = `${imgClass} kg-image--${payload.imageStyle}`;
}
img.setAttribute('src', payload.src);
img.setAttribute('class', imgClass);

figure.appendChild(img);

if (payload.caption) {
Expand Down
12 changes: 7 additions & 5 deletions packages/kg-default-cards/lib/cards/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
var hr = require('./hr'),
html = require('./html'),
image = require('./image'),
markdown = require('./markdown'),
cardMarkdown = require('./card-markdown');
'use strict';

const hr = require('./hr');
const html = require('./html');
const image = require('./image');
const markdown = require('./markdown');
const cardMarkdown = require('./card-markdown');

module.exports = [hr, html, image, markdown, cardMarkdown];
21 changes: 12 additions & 9 deletions packages/kg-default-cards/lib/cards/markdown.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
'use strict';

module.exports = {
name: 'markdown',
type: 'dom',
render: function (opts) {
var converters = require('../converters'),
html, element;

let converters = require('../converters');
let payload = opts.payload;
let version = opts.options.version;
// convert markdown to HTML ready for insertion into dom
html = '<div class="kg-card-markdown">'
+ converters.markdownConverter.render(opts.payload.markdown || '')
+ '</div>';
let html = converters.markdownConverter.render(payload.markdown || '');

// Ghost 1.0's markdown-only renderer wrapped cards
if (version === 1) {
html = `<div class="kg-card-markdown">${html}</div>`;
}

// use the SimpleDOM document to create a raw HTML section.
// avoids parsing/rendering of potentially broken or unsupported HTML
element = opts.env.dom.createRawHTMLSection(html);

return element;
return opts.env.dom.createRawHTMLSection(html);
}
};
15 changes: 8 additions & 7 deletions packages/kg-default-cards/test/cards/hr_spec.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
var should = require('should'), // jshint ignore:line
card = require('../../../../../server/lib/mobiledoc/cards/hr'),
SimpleDom = require('simple-dom'),
opts;
'use strict';

const should = require('should'); // jshint ignore:line
const card = require('../../../../../server/lib/mobiledoc/cards/hr');
const SimpleDom = require('simple-dom');
const serializer = new SimpleDom.HTMLSerializer(SimpleDom.voidMap);

describe('HR card', function () {
it('generates a horizontal rule', function () {
opts = {
let opts = {
env: {
dom: new SimpleDom.Document()
}
};

var serializer = new SimpleDom.HTMLSerializer([]);
serializer.serialize(card.render(opts)).should.match('<hr></hr>');
serializer.serialize(card.render(opts)).should.match('<hr>');
});
});
40 changes: 12 additions & 28 deletions packages/kg-default-cards/test/cards/html_spec.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
var should = require('should'), // jshint ignore:line
card = require('../../../../../server/lib/mobiledoc/cards/html'),
SimpleDom = require('simple-dom'),
opts;
'use strict';

const should = require('should'); // jshint ignore:line
const card = require('../../../../../server/lib/mobiledoc/cards/html');
const SimpleDom = require('simple-dom');
const serializer = new SimpleDom.HTMLSerializer(SimpleDom.voidMap);

describe('HTML card', function () {
it('HTML Card renders', function () {
opts = {
let opts = {
env: {
dom: new SimpleDom.Document()
},
Expand All @@ -14,12 +16,11 @@ describe('HTML card', function () {
}
};

var serializer = new SimpleDom.HTMLSerializer([]);
serializer.serialize(card.render(opts)).should.match('<div class="kg-card-html"><h1>HEADING</h1><p>PARAGRAPH</p></div>');
serializer.serialize(card.render(opts)).should.match('<h1>HEADING</h1><p>PARAGRAPH</p>');
});

it('Plain content renders', function () {
opts = {
let opts = {
env: {
dom: new SimpleDom.Document()
},
Expand All @@ -28,12 +29,11 @@ describe('HTML card', function () {
}
};

var serializer = new SimpleDom.HTMLSerializer([]);
serializer.serialize(card.render(opts)).should.match('<div class="kg-card-html">CONTENT</div>');
serializer.serialize(card.render(opts)).should.match('CONTENT');
});

it('Invalid HTML returns', function () {
opts = {
let opts = {
env: {
dom: new SimpleDom.Document()
},
Expand All @@ -42,22 +42,6 @@ describe('HTML card', function () {
}
};

var serializer = new SimpleDom.HTMLSerializer([]);
serializer.serialize(card.render(opts)).should.match('<div class="kg-card-html"><h1>HEADING<</div>');
});

it('Caption renders', function () {
opts = {
env: {
dom: new SimpleDom.Document()
},
payload: {
html: '<iframe src="http://vimeo.com"></iframe>',
caption: 'Embed caption test'
}
};

var serializer = new SimpleDom.HTMLSerializer([]);
serializer.serialize(card.render(opts)).should.match('<div class="kg-card-html"><iframe src="http://vimeo.com"></iframe><p>Embed caption test</p></div>');
serializer.serialize(card.render(opts)).should.match('<h1>HEADING<');
});
});
64 changes: 54 additions & 10 deletions packages/kg-default-cards/test/cards/image_spec.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
var should = require('should'), // jshint ignore:line
card = require('../../../../../server/lib/mobiledoc/cards/image'),
SimpleDom = require('simple-dom'),
opts;
'use strict';

const should = require('should'); // jshint ignore:line
const card = require('../../../../../server/lib/mobiledoc/cards/image');
const SimpleDom = require('simple-dom');
const serializer = new SimpleDom.HTMLSerializer(SimpleDom.voidMap);

describe('Image card', function () {
it('generates an image', function () {
opts = {
let opts = {
env: {
dom: new SimpleDom.Document()
},
Expand All @@ -14,12 +16,11 @@ describe('Image card', function () {
}
};

var serializer = new SimpleDom.HTMLSerializer([]);
serializer.serialize(card.render(opts)).should.match('<figure><img src="https://www.ghost.org/image.png"></img></figure>');
serializer.serialize(card.render(opts)).should.eql('<figure class="kg-image-card"><img src="https://www.ghost.org/image.png" class="kg-image"></figure>');
});

it('generates an image with caption', function () {
opts = {
let opts = {
env: {
dom: new SimpleDom.Document()
},
Expand All @@ -29,7 +30,50 @@ describe('Image card', function () {
}
};

var serializer = new SimpleDom.HTMLSerializer([]);
serializer.serialize(card.render(opts)).should.match('<figure><img src="https://www.ghost.org/image.png"></img><figcaption>Test caption</figcaption></figure>');
serializer.serialize(card.render(opts)).should.eql('<figure class="kg-image-card"><img src="https://www.ghost.org/image.png" class="kg-image"><figcaption>Test caption</figcaption></figure>');
});

describe('sizes', function () {
it('standard', function () {
let opts = {
env: {
dom: new SimpleDom.Document()
},
payload: {
src: 'https://www.ghost.org/image.png',
imageStyle: ''
}
};

serializer.serialize(card.render(opts)).should.eql('<figure class="kg-image-card"><img src="https://www.ghost.org/image.png" class="kg-image"></figure>');
});

it('wide', function () {
let opts = {
env: {
dom: new SimpleDom.Document()
},
payload: {
src: 'https://www.ghost.org/image.png',
imageStyle: 'wide'
}
};

serializer.serialize(card.render(opts)).should.eql('<figure class="kg-image-card"><img src="https://www.ghost.org/image.png" class="kg-image kg-image--wide"></figure>');
});

it('full', function () {
let opts = {
env: {
dom: new SimpleDom.Document()
},
payload: {
src: 'https://www.ghost.org/image.png',
imageStyle: 'full'
}
};

serializer.serialize(card.render(opts)).should.eql('<figure class="kg-image-card"><img src="https://www.ghost.org/image.png" class="kg-image kg-image--full"></figure>');
});
});
});
98 changes: 70 additions & 28 deletions packages/kg-default-cards/test/cards/markdown_spec.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,76 @@
var should = require('should'), // jshint ignore:line
card = require('../../../../../server/lib/mobiledoc/cards/markdown'),
SimpleDom = require('simple-dom'),
opts;
'use strict';

const should = require('should'); // jshint ignore:line
const card = require('../../../../../server/lib/mobiledoc/cards/markdown');
const SimpleDom = require('simple-dom');
const serializer = new SimpleDom.HTMLSerializer(SimpleDom.voidMap);

describe('Markdown card', function () {
it('Markdown Card renders', function () {
opts = {
env: {
dom: new SimpleDom.Document()
},
payload: {
markdown: '#HEADING\r\n- list\r\n- items'
}
};

var serializer = new SimpleDom.HTMLSerializer([]);
serializer.serialize(card.render(opts)).should.match('<div class="kg-card-markdown"><h1 id="heading">HEADING</h1>\n<ul>\n<li>list</li>\n<li>items</li>\n</ul>\n</div>');
describe('version 1', function () {
it('Markdown Card renders', function () {
let opts = {
env: {
dom: new SimpleDom.Document()
},
payload: {
markdown: '#HEADING\r\n- list\r\n- items'
},
options: {
version: 1
}
};

serializer.serialize(card.render(opts)).should.match('<div class="kg-card-markdown"><h1 id="heading">HEADING</h1>\n<ul>\n<li>list</li>\n<li>items</li>\n</ul>\n</div>');
});

it('Accepts invalid HTML in markdown', function () {
let opts = {
env: {
dom: new SimpleDom.Document()
},
payload: {
markdown: '#HEADING\r\n<h2>Heading 2>'
},
options: {
version: 1
}
};

serializer.serialize(card.render(opts)).should.match('<div class="kg-card-markdown"><h1 id="heading">HEADING</h1>\n<h2>Heading 2></div>');
});
});

it('Accepts invalid HTML in markdown', function () {
opts = {
env: {
dom: new SimpleDom.Document()
},
payload: {
markdown: '#HEADING\r\n<h2>Heading 2>'
}
};

var serializer = new SimpleDom.HTMLSerializer([]);
serializer.serialize(card.render(opts)).should.match('<div class="kg-card-markdown"><h1 id="heading">HEADING</h1>\n<h2>Heading 2></div>');
describe('version 2', function () {
it('Markdown Card renders', function () {
let opts = {
env: {
dom: new SimpleDom.Document()
},
payload: {
markdown: '#HEADING\r\n- list\r\n- items'
},
options: {
version: 2
}
};

serializer.serialize(card.render(opts)).should.match('<h1 id="heading">HEADING</h1>\n<ul>\n<li>list</li>\n<li>items</li>\n</ul>\n');
});

it('Accepts invalid HTML in markdown', function () {
let opts = {
env: {
dom: new SimpleDom.Document()
},
payload: {
markdown: '#HEADING\r\n<h2>Heading 2>'
},
options: {
version: 2
}
};

serializer.serialize(card.render(opts)).should.match('<h1 id="heading">HEADING</h1>\n<h2>Heading 2>');
});
});
});

0 comments on commit f6effeb

Please sign in to comment.