mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-30 21:40:39 +03:00
🐛 Fixed rendering and url transformation of v1 "card-markdown" aliased cards
no issue - Ghost 1.x stored markdown cards with the name `card-markdown`, this was changed in Ghost 2.x to be `markdown`. To keep compatibility with the older mobiledoc content the `markdown` card was aliased using a straightforward `Object.assign()`. Unfortunately this failed to work adequately when the url transformation functions were added to cards and resulted in corrupted data being returned in API responses - moved the markdown card definition into a factory function so that a clean card definition object can be used for both the `markdown` and `card-markdown` cards
This commit is contained in:
parent
4f0ca2914f
commit
6b3c4a59b4
40
core/server/lib/mobiledoc/cards/_markdown.js
Normal file
40
core/server/lib/mobiledoc/cards/_markdown.js
Normal file
@ -0,0 +1,40 @@
|
||||
// this is a function so that when it's aliased across multiple cards we do not
|
||||
// end up modifying the object by reference
|
||||
module.exports = function markdownCardDefinition() {
|
||||
return {
|
||||
name: 'markdown',
|
||||
type: 'dom',
|
||||
render: function (opts) {
|
||||
let converters = require('../converters');
|
||||
let payload = opts.payload;
|
||||
let version = opts.options && opts.options.version || 2;
|
||||
// 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
|
||||
*/
|
||||
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
|
||||
return opts.env.dom.createRawHTMLSection(html);
|
||||
},
|
||||
|
||||
absoluteToRelative(urlUtils, payload, options) {
|
||||
payload.markdown = payload.markdown && urlUtils.markdownAbsoluteToRelative(payload.markdown, options);
|
||||
return payload;
|
||||
},
|
||||
|
||||
relativeToAbsolute(urlUtils, payload, options) {
|
||||
payload.markdown = payload.markdown && urlUtils.markdownRelativeToAbsolute(payload.markdown, options);
|
||||
return payload;
|
||||
}
|
||||
};
|
||||
};
|
@ -1,8 +1,9 @@
|
||||
// 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 markdownCard = require('./_markdown');
|
||||
const createCard = require('../create-card');
|
||||
|
||||
module.exports = createCard(
|
||||
Object.assign({}, markdownCard, {name: 'card-markdown'})
|
||||
);
|
||||
const v1CompatMarkdownCard = markdownCard();
|
||||
v1CompatMarkdownCard.name = 'card-markdown';
|
||||
|
||||
module.exports = createCard(v1CompatMarkdownCard);
|
||||
|
@ -1,38 +1,6 @@
|
||||
const markdownCard = require('./_markdown');
|
||||
const createCard = require('../create-card');
|
||||
|
||||
module.exports = createCard({
|
||||
name: 'markdown',
|
||||
type: 'dom',
|
||||
render: function (opts) {
|
||||
let converters = require('../converters');
|
||||
let payload = opts.payload;
|
||||
let version = opts.options && opts.options.version || 2;
|
||||
// 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
|
||||
*/
|
||||
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
|
||||
return opts.env.dom.createRawHTMLSection(html);
|
||||
},
|
||||
|
||||
absoluteToRelative(urlUtils, payload, options) {
|
||||
payload.markdown = payload.markdown && urlUtils.markdownAbsoluteToRelative(payload.markdown, options);
|
||||
return payload;
|
||||
},
|
||||
|
||||
relativeToAbsolute(urlUtils, payload, options) {
|
||||
payload.markdown = payload.markdown && urlUtils.markdownRelativeToAbsolute(payload.markdown, options);
|
||||
return payload;
|
||||
}
|
||||
});
|
||||
// uses the _markdown card definition function so that the card definition
|
||||
// can be re-used in aliased cards
|
||||
module.exports = createCard(markdownCard());
|
||||
|
83
core/test/unit/lib/mobiledoc/cards/card-markdown_spec.js
Normal file
83
core/test/unit/lib/mobiledoc/cards/card-markdown_spec.js
Normal file
@ -0,0 +1,83 @@
|
||||
const should = require('should');
|
||||
const card = require('../../../../../server/lib/mobiledoc/cards/card-markdown');
|
||||
const SimpleDom = require('simple-dom');
|
||||
const serializer = new SimpleDom.HTMLSerializer(SimpleDom.voidMap);
|
||||
|
||||
describe('Markdown card (v1 compatibility card)', function () {
|
||||
it('renders', function () {
|
||||
let opts = {
|
||||
env: {
|
||||
dom: new SimpleDom.Document()
|
||||
},
|
||||
payload: {
|
||||
markdown: '#HEADING\r\n- list\r\n- items'
|
||||
}
|
||||
};
|
||||
|
||||
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 () {
|
||||
let opts = {
|
||||
env: {
|
||||
dom: new SimpleDom.Document()
|
||||
},
|
||||
payload: {
|
||||
markdown: '#HEADING\r\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 () {
|
||||
let opts = {
|
||||
env: {
|
||||
dom: new SimpleDom.Document()
|
||||
},
|
||||
payload: {
|
||||
markdown: undefined
|
||||
}
|
||||
};
|
||||
|
||||
serializer.serialize(card.render(opts)).should.eql('');
|
||||
});
|
||||
|
||||
it('[deprecated] version 1', 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.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-->');
|
||||
});
|
||||
|
||||
it('transforms urls absolute to relative', function () {
|
||||
let payload = {
|
||||
markdown: 'A link to [an internal post](http://127.0.0.1:2369/post)'
|
||||
};
|
||||
|
||||
const transformed = card.absoluteToRelative(payload, {});
|
||||
|
||||
transformed.markdown
|
||||
.should.equal('A link to [an internal post](/post)');
|
||||
});
|
||||
|
||||
it('transforms urls relative to absolute', function () {
|
||||
let payload = {
|
||||
markdown: 'A link to [an internal post](/post)'
|
||||
};
|
||||
|
||||
const transformed = card.relativeToAbsolute(payload, {});
|
||||
|
||||
transformed.markdown
|
||||
.should.equal('A link to [an internal post](http://127.0.0.1:2369/post)');
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user