mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-01 23:37:43 +03:00
Updated mobiledoc renderer to insert begin/end HTML comments around cards
no issue We're creating tooling to convert HTML to Ghost flavoured mobiledoc, however we have cards that allow arbitrary content without a wrapper element which means that we're unable to do a 1:1 mapping of mobiledoc->html->mobiledoc. To work around this problem we now output HTML comments before/after the output of each card so that our converter can extract card content correctly when parsing HTML. - added `createCard` method which wraps a card's `render()` method to add begin/end comments and updated all cards to use it - only takes affect for newly added or re-saved posts/pages
This commit is contained in:
parent
23d54803e6
commit
4f9e687f62
@ -1,5 +1,8 @@
|
||||
// this card is just an alias of the `markdown` card which is necessary because
|
||||
// our markdown-only editor was using the `card-markdown` card name
|
||||
const markdownCard = require('./markdown');
|
||||
const createCard = require('../create-card');
|
||||
|
||||
module.exports = Object.assign({}, markdownCard, {name: 'card-markdown'});
|
||||
module.exports = createCard(
|
||||
Object.assign({}, markdownCard, {name: 'card-markdown'})
|
||||
);
|
||||
|
@ -1,4 +1,6 @@
|
||||
module.exports = {
|
||||
const createCard = require('../create-card');
|
||||
|
||||
module.exports = createCard({
|
||||
name: 'code',
|
||||
type: 'dom',
|
||||
render(opts) {
|
||||
@ -21,4 +23,4 @@ module.exports = {
|
||||
|
||||
return pre;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
@ -1,4 +1,6 @@
|
||||
module.exports = {
|
||||
const createCard = require('../create-card');
|
||||
|
||||
module.exports = createCard({
|
||||
name: 'embed',
|
||||
type: 'dom',
|
||||
render(opts) {
|
||||
@ -23,4 +25,4 @@ module.exports = {
|
||||
|
||||
return figure;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
@ -1,5 +1,3 @@
|
||||
const MAX_IMG_PER_ROW = 3;
|
||||
|
||||
/**
|
||||
* <figure class="kg-gallery-card kg-width-wide">
|
||||
* <div class="kg-gallery-container>
|
||||
@ -17,7 +15,11 @@ const MAX_IMG_PER_ROW = 3;
|
||||
* </figure>
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
const createCard = require('../create-card');
|
||||
|
||||
const MAX_IMG_PER_ROW = 3;
|
||||
|
||||
module.exports = createCard({
|
||||
name: 'gallery',
|
||||
type: 'dom',
|
||||
render(opts) {
|
||||
@ -107,4 +109,4 @@ module.exports = {
|
||||
|
||||
return figure;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
@ -1,7 +1,9 @@
|
||||
module.exports = {
|
||||
const createCard = require('../create-card');
|
||||
|
||||
module.exports = createCard({
|
||||
name: 'hr',
|
||||
type: 'dom',
|
||||
render(opts) {
|
||||
return opts.env.dom.createElement('hr');
|
||||
}
|
||||
};
|
||||
});
|
||||
|
@ -1,4 +1,6 @@
|
||||
module.exports = {
|
||||
const createCard = require('../create-card');
|
||||
|
||||
module.exports = createCard({
|
||||
name: 'html',
|
||||
type: 'dom',
|
||||
render(opts) {
|
||||
@ -10,4 +12,4 @@ module.exports = {
|
||||
// avoids parsing/rendering of potentially broken or unsupported HTML
|
||||
return opts.env.dom.createRawHTMLSection(opts.payload.html);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
@ -1,4 +1,6 @@
|
||||
module.exports = {
|
||||
const createCard = require('../create-card');
|
||||
|
||||
module.exports = createCard({
|
||||
name: 'image',
|
||||
type: 'dom',
|
||||
render(opts) {
|
||||
@ -38,4 +40,4 @@ module.exports = {
|
||||
|
||||
return figure;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
@ -1,4 +1,6 @@
|
||||
module.exports = {
|
||||
const createCard = require('../create-card');
|
||||
|
||||
module.exports = createCard({
|
||||
name: 'markdown',
|
||||
type: 'dom',
|
||||
render: function (opts) {
|
||||
@ -8,6 +10,10 @@ module.exports = {
|
||||
// convert markdown to HTML ready for insertion into dom
|
||||
let html = converters.markdownConverter.render(payload.markdown || '');
|
||||
|
||||
if (!html) {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Ghost 1.0's markdown-only renderer wrapped cards. Remove in Ghost 3.0
|
||||
*/
|
||||
@ -19,4 +25,4 @@ module.exports = {
|
||||
// avoids parsing/rendering of potentially broken or unsupported HTML
|
||||
return opts.env.dom.createRawHTMLSection(html);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
28
core/server/lib/mobiledoc/create-card.js
Normal file
28
core/server/lib/mobiledoc/create-card.js
Normal file
@ -0,0 +1,28 @@
|
||||
module.exports = function createCard(card) {
|
||||
const {name, type} = card;
|
||||
|
||||
return {
|
||||
name,
|
||||
type,
|
||||
render({env, payload, options}) {
|
||||
const {dom} = env;
|
||||
const cleanName = name.replace(/^card-/, '');
|
||||
|
||||
const cardOutput = card.render({env, payload, options});
|
||||
|
||||
if (!cardOutput) {
|
||||
return cardOutput;
|
||||
}
|
||||
|
||||
const beginComment = dom.createComment(`kg-card-begin: ${cleanName}`);
|
||||
const endComment = dom.createComment(`kg-card-end: ${cleanName}`);
|
||||
const fragment = dom.createDocumentFragment();
|
||||
|
||||
fragment.appendChild(beginComment);
|
||||
fragment.appendChild(cardOutput);
|
||||
fragment.appendChild(endComment);
|
||||
|
||||
return fragment;
|
||||
}
|
||||
};
|
||||
};
|
@ -14,7 +14,7 @@ describe('Code card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.match('<pre><code><p>Test</p></code></pre>');
|
||||
serializer.serialize(card.render(opts)).should.match('<!--kg-card-begin: code--><pre><code><p>Test</p></code></pre><!--kg-card-end: code-->');
|
||||
});
|
||||
|
||||
it('Renders language class if provided', function () {
|
||||
@ -28,7 +28,7 @@ describe('Code card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.match('<pre><code class="language-html"><p>Test</p></code></pre>');
|
||||
serializer.serialize(card.render(opts)).should.match('<!--kg-card-begin: code--><pre><code class="language-html"><p>Test</p></code></pre><!--kg-card-end: code-->');
|
||||
});
|
||||
|
||||
it('Renders nothing when payload is undefined', function () {
|
||||
|
@ -14,7 +14,7 @@ describe('Embed card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.match('<figure class="kg-card kg-embed-card"><h1>HEADING</h1><p>PARAGRAPH</p></figure>');
|
||||
serializer.serialize(card.render(opts)).should.match('<!--kg-card-begin: embed--><figure class="kg-card kg-embed-card"><h1>HEADING</h1><p>PARAGRAPH</p></figure><!--kg-card-end: embed-->');
|
||||
});
|
||||
|
||||
it('Plain content renders', function () {
|
||||
@ -27,7 +27,7 @@ describe('Embed card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.match('<figure class="kg-card kg-embed-card">CONTENT</figure>');
|
||||
serializer.serialize(card.render(opts)).should.match('<!--kg-card-begin: embed--><figure class="kg-card kg-embed-card">CONTENT</figure><!--kg-card-end: embed-->');
|
||||
});
|
||||
|
||||
it('Invalid HTML returns', function () {
|
||||
@ -40,7 +40,7 @@ describe('Embed card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.match('<figure class="kg-card kg-embed-card"><h1>HEADING<</figure>');
|
||||
serializer.serialize(card.render(opts)).should.match('<!--kg-card-begin: embed--><figure class="kg-card kg-embed-card"><h1>HEADING<</figure><!--kg-card-end: embed-->');
|
||||
});
|
||||
|
||||
it('Renders nothing when payload is undefined', function () {
|
||||
@ -67,6 +67,6 @@ describe('Embed card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.match('<figure class="kg-card kg-embed-card kg-card-hascaption">Testing<figcaption><strong>Caption</strong></figcaption></figure>');
|
||||
serializer.serialize(card.render(opts)).should.match('<!--kg-card-begin: embed--><figure class="kg-card kg-embed-card kg-card-hascaption">Testing<figcaption><strong>Caption</strong></figcaption></figure><!--kg-card-end: embed-->');
|
||||
});
|
||||
});
|
||||
|
@ -74,7 +74,7 @@ describe('Gallery card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.eql('<figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="/content/images/2018/08/NatGeo01-9.jpg" width="3200" height="1600"></div><div class="kg-gallery-image"><img src="/content/images/2018/08/NatGeo02-10.jpg" width="3200" height="1600"></div><div class="kg-gallery-image"><img src="/content/images/2018/08/NatGeo03-6.jpg" width="3200" height="1600"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="/content/images/2018/08/NatGeo04-7.jpg" width="3200" height="1600" alt="Alt test"></div><div class="kg-gallery-image"><img src="/content/images/2018/08/NatGeo05-4.jpg" width="3200" height="1600" title="Title test"></div><div class="kg-gallery-image"><img src="/content/images/2018/08/NatGeo06-6.jpg" width="3200" height="1600"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="/content/images/2018/08/NatGeo07-5.jpg" width="3200" height="1600"></div><div class="kg-gallery-image"><img src="/content/images/2018/08/NatGeo09-8.jpg" width="3200" height="1600"></div></div></div><figcaption>Test caption</figcaption></figure>');
|
||||
serializer.serialize(card.render(opts)).should.eql('<!--kg-card-begin: gallery--><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="/content/images/2018/08/NatGeo01-9.jpg" width="3200" height="1600"></div><div class="kg-gallery-image"><img src="/content/images/2018/08/NatGeo02-10.jpg" width="3200" height="1600"></div><div class="kg-gallery-image"><img src="/content/images/2018/08/NatGeo03-6.jpg" width="3200" height="1600"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="/content/images/2018/08/NatGeo04-7.jpg" width="3200" height="1600" alt="Alt test"></div><div class="kg-gallery-image"><img src="/content/images/2018/08/NatGeo05-4.jpg" width="3200" height="1600" title="Title test"></div><div class="kg-gallery-image"><img src="/content/images/2018/08/NatGeo06-6.jpg" width="3200" height="1600"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="/content/images/2018/08/NatGeo07-5.jpg" width="3200" height="1600"></div><div class="kg-gallery-image"><img src="/content/images/2018/08/NatGeo09-8.jpg" width="3200" height="1600"></div></div></div><figcaption>Test caption</figcaption></figure><!--kg-card-end: gallery-->');
|
||||
});
|
||||
|
||||
it('renders nothing with no images', function () {
|
||||
@ -136,6 +136,6 @@ describe('Gallery card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.eql('<figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="/content/images/2018/08/NatGeo01-9.jpg" width="3200" height="1600"></div><div class="kg-gallery-image"><img src="/content/images/2018/08/NatGeo03-6.jpg" width="3200" height="1600"></div></div></div><figcaption>Test caption</figcaption></figure>');
|
||||
serializer.serialize(card.render(opts)).should.eql('<!--kg-card-begin: gallery--><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="/content/images/2018/08/NatGeo01-9.jpg" width="3200" height="1600"></div><div class="kg-gallery-image"><img src="/content/images/2018/08/NatGeo03-6.jpg" width="3200" height="1600"></div></div></div><figcaption>Test caption</figcaption></figure><!--kg-card-end: gallery-->');
|
||||
});
|
||||
});
|
||||
|
@ -11,6 +11,6 @@ describe('HR card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.match('<hr>');
|
||||
serializer.serialize(card.render(opts)).should.match('<!--kg-card-begin: hr--><hr><!--kg-card-end: hr-->');
|
||||
});
|
||||
});
|
||||
|
@ -14,7 +14,7 @@ describe('HTML card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.match('<h1>HEADING</h1><p>PARAGRAPH</p>');
|
||||
serializer.serialize(card.render(opts)).should.eql('<!--kg-card-begin: html--><h1>HEADING</h1><p>PARAGRAPH</p><!--kg-card-end: html-->');
|
||||
});
|
||||
|
||||
it('Plain content renders', function () {
|
||||
@ -27,7 +27,7 @@ describe('HTML card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.match('CONTENT');
|
||||
serializer.serialize(card.render(opts)).should.eql('<!--kg-card-begin: html-->CONTENT<!--kg-card-end: html-->');
|
||||
});
|
||||
|
||||
it('Invalid HTML returns', function () {
|
||||
@ -40,7 +40,7 @@ describe('HTML card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.match('<h1>HEADING<');
|
||||
serializer.serialize(card.render(opts)).should.eql('<!--kg-card-begin: html--><h1>HEADING<<!--kg-card-end: html-->');
|
||||
});
|
||||
|
||||
it('Renders nothing when payload is undefined', function () {
|
||||
@ -53,6 +53,6 @@ describe('HTML card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.match('');
|
||||
serializer.serialize(card.render(opts)).should.eql('');
|
||||
});
|
||||
});
|
||||
|
@ -14,7 +14,7 @@ describe('Image card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.eql('<figure class="kg-card kg-image-card"><img src="https://www.ghost.org/image.png" class="kg-image"></figure>');
|
||||
serializer.serialize(card.render(opts)).should.eql('<!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://www.ghost.org/image.png" class="kg-image"></figure><!--kg-card-end: image-->');
|
||||
});
|
||||
|
||||
it('renders an image with caption', function () {
|
||||
@ -28,7 +28,7 @@ describe('Image card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.eql('<figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.ghost.org/image.png" class="kg-image"><figcaption><b>Test caption</b></figcaption></figure>');
|
||||
serializer.serialize(card.render(opts)).should.eql('<!--kg-card-begin: image--><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.ghost.org/image.png" class="kg-image"><figcaption><b>Test caption</b></figcaption></figure><!--kg-card-end: image-->');
|
||||
});
|
||||
|
||||
it('renders an image with alt text', function () {
|
||||
@ -42,7 +42,7 @@ describe('Image card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.eql('<figure class="kg-card kg-image-card"><img src="https://www.ghost.org/image.png" class="kg-image" alt="example image"></figure>');
|
||||
serializer.serialize(card.render(opts)).should.eql('<!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://www.ghost.org/image.png" class="kg-image" alt="example image"></figure><!--kg-card-end: image-->');
|
||||
});
|
||||
|
||||
it('renders an image with title attribute', function () {
|
||||
@ -56,7 +56,7 @@ describe('Image card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.eql('<figure class="kg-card kg-image-card"><img src="https://www.ghost.org/image.png" class="kg-image" title="example image"></figure>');
|
||||
serializer.serialize(card.render(opts)).should.eql('<!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://www.ghost.org/image.png" class="kg-image" title="example image"></figure><!--kg-card-end: image-->');
|
||||
});
|
||||
|
||||
it('renders nothing with no src', function () {
|
||||
@ -85,7 +85,7 @@ describe('Image card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.eql('<figure class="kg-card kg-image-card"><img src="https://www.ghost.org/image.png" class="kg-image"></figure>');
|
||||
serializer.serialize(card.render(opts)).should.eql('<!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://www.ghost.org/image.png" class="kg-image"></figure><!--kg-card-end: image-->');
|
||||
});
|
||||
|
||||
it('wide', function () {
|
||||
@ -99,7 +99,7 @@ describe('Image card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.eql('<figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.ghost.org/image.png" class="kg-image"></figure>');
|
||||
serializer.serialize(card.render(opts)).should.eql('<!--kg-card-begin: image--><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.ghost.org/image.png" class="kg-image"></figure><!--kg-card-end: image-->');
|
||||
});
|
||||
|
||||
it('full', function () {
|
||||
@ -113,7 +113,7 @@ describe('Image card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.eql('<figure class="kg-card kg-image-card kg-width-full"><img src="https://www.ghost.org/image.png" class="kg-image"></figure>');
|
||||
serializer.serialize(card.render(opts)).should.eql('<!--kg-card-begin: image--><figure class="kg-card kg-image-card kg-width-full"><img src="https://www.ghost.org/image.png" class="kg-image"></figure><!--kg-card-end: image-->');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -15,7 +15,7 @@ describe('Markdown card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
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');
|
||||
serializer.serialize(card.render(opts)).should.eql('<!--kg-card-begin: markdown--><h1 id="heading">HEADING</h1>\n<ul>\n<li>list</li>\n<li>items</li>\n</ul>\n<!--kg-card-end: markdown-->');
|
||||
});
|
||||
|
||||
it('Accepts invalid HTML in markdown', function () {
|
||||
@ -28,7 +28,7 @@ describe('Markdown card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.match('<h1 id="heading">HEADING</h1>\n<h2>Heading 2>');
|
||||
serializer.serialize(card.render(opts)).should.eql('<!--kg-card-begin: markdown--><h1 id="heading">HEADING</h1>\n<h2>Heading 2><!--kg-card-end: markdown-->');
|
||||
});
|
||||
|
||||
it('Renders nothing when payload is undefined', function () {
|
||||
@ -41,7 +41,7 @@ describe('Markdown card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.match('');
|
||||
serializer.serialize(card.render(opts)).should.eql('');
|
||||
});
|
||||
|
||||
it('[deprecated] version 1', function () {
|
||||
@ -57,7 +57,7 @@ describe('Markdown card', function () {
|
||||
}
|
||||
};
|
||||
|
||||
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>');
|
||||
serializer.serialize(card.render(opts)).should.eql('<!--kg-card-begin: markdown--><div class="kg-card-markdown"><h1 id="heading">HEADING</h1>\n<ul>\n<li>list</li>\n<li>items</li>\n</ul>\n</div><!--kg-card-end: markdown-->');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -57,7 +57,7 @@ describe('Mobiledoc converter', function () {
|
||||
]
|
||||
};
|
||||
|
||||
converter.render(mobiledoc, 2).should.eql('<p>One<br>Two</p><h1 id="markdowncard">Markdown card</h1>\n<p>Some markdown</p>\n<p>Three</p><hr><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="/content/images/2018/04/NatGeo06.jpg" class="kg-image"><figcaption>Birdies</figcaption></figure><p>Four</p><h2>HTML card</h2>\n<div><p>Some HTML</p></div><figure class="kg-card kg-embed-card"><h2>Embed card</h2></figure><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"></div></figure>');
|
||||
converter.render(mobiledoc, 2).should.eql('<p>One<br>Two</p><!--kg-card-begin: markdown--><h1 id="markdowncard">Markdown card</h1>\n<p>Some markdown</p>\n<!--kg-card-end: markdown--><p>Three</p><!--kg-card-begin: hr--><hr><!--kg-card-end: hr--><!--kg-card-begin: image--><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="/content/images/2018/04/NatGeo06.jpg" class="kg-image"><figcaption>Birdies</figcaption></figure><!--kg-card-end: image--><p>Four</p><!--kg-card-begin: html--><h2>HTML card</h2>\n<div><p>Some HTML</p></div><!--kg-card-end: html--><!--kg-card-begin: embed--><figure class="kg-card kg-embed-card"><h2>Embed card</h2></figure><!--kg-card-end: embed--><!--kg-card-begin: gallery--><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"></div></figure><!--kg-card-end: gallery-->');
|
||||
});
|
||||
|
||||
it('removes final blank paragraph', function () {
|
||||
|
Loading…
Reference in New Issue
Block a user