0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-11 02:12:21 -05:00

🐛 fix: make small media types not stretch (#7265)

no issue

Fixes a bug with displaying small media types like images or gif. Two reasons for that:
1. In many cases, we only have the relative URL instead of the absolute URL for the media source and therefore, `Amperize` module wasn't able to detect the image size and set the default image size of `width="600"` and `height="400"`.
2. Even if we have detected the correct image size, the attribute `layout="default"` would still make it strech. This issue is fixed in `Amperize`, but it wasn't merged at this time, so I set the dependency on my fork.

Adds `amp-anim` to the `.post-content` class, to have same CSS style as an image.
This commit is contained in:
Aileen Nowak 2016-08-25 11:09:25 +02:00 committed by Katharina Irrgang
parent 84a35a4753
commit 93ee19f36e
4 changed files with 155 additions and 135 deletions

View file

@ -11,6 +11,8 @@ var hbs = require('express-hbs'),
Amperize = require('amperize'),
moment = require('moment'),
sanitizeHtml = require('sanitize-html'),
config = require('../../../../config'),
makeAbsoluteUrl = require('../../../../utils/make-absolute-urls'),
amperize = new Amperize(),
amperizeCache = {},
allowedAMPTags = [],
@ -40,6 +42,9 @@ function getAmperizeHTML(html, post) {
return;
}
// make relative URLs abolute
html = makeAbsoluteUrl(html, config.url, post.url).html();
if (!amperizeCache[post.id] || moment(new Date(amperizeCache[post.id].updated_at)).diff(new Date(post.updated_at)) < 0) {
return new Promise(function (resolve, reject) {
amperize.parse(html, function (err, res) {
@ -64,7 +69,7 @@ function ampContent() {
return Promise.props(amperizeHTML).then(function (result) {
ampHTML = result.amperize || '';
// let's sanitize our html!!!
// let's sanitize our HTML!!!
cleanHTML = sanitizeHtml(ampHTML, {
allowedTags: allowedAMPTags,
allowedAttributes: false,

View file

@ -692,7 +692,8 @@
/* Keep images centered, and allow images wider than the main
text column to break out. */
.post-content amp-img {
.post-content amp-img,
.post-content amp-anim {
/* Centers an image by (1) pushing its left edge to the
center of its container and (2) shifting the entire image
in the opposite direction by half its own width.

View file

@ -1,5 +1,6 @@
var should = require('should'),
rewire = require('rewire'),
configUtils = require('../../../../test/utils/configUtils'),
// Stuff we are testing
ampContentHelper = rewire('../lib/helpers/amp_content');
@ -24,89 +25,6 @@ describe('{{amp_content}} helper', function () {
}).catch(done);
});
it('can render content from cache', function (done) {
var testData = {
html: 'Hello World',
updated_at: 'Wed Jul 27 2016 18:17:22 GMT+0200 (CEST)',
id: 1
},
ampCachedResult,
ampResult = ampContentHelper.call(testData),
amperizeCache = ampContentHelper.__get__('amperizeCache');
ampResult.then(function (rendered) {
should.exist(rendered);
should.exist(amperizeCache);
rendered.string.should.equal(testData.html);
amperizeCache[1].should.have.property('updated_at', 'Wed Jul 27 2016 18:17:22 GMT+0200 (CEST)');
amperizeCache[1].should.have.property('amp', testData.html);
// call it again, to make it fetch from cache
ampCachedResult = ampContentHelper.call(testData);
ampCachedResult.then(function (rendered) {
should.exist(rendered);
should.exist(amperizeCache);
amperizeCache[1].should.have.property('updated_at', 'Wed Jul 27 2016 18:17:22 GMT+0200 (CEST)');
amperizeCache[1].should.have.property('amp', testData.html);
done();
});
}).catch(done);
});
it('fetches new AMP HTML if post was changed', function (done) {
var testData1 = {
html: 'Hello World',
updated_at: 'Wed Jul 27 2016 18:17:22 GMT+0200 (CEST)',
id: 1
},
testData2 = {
html: 'Hello Ghost',
updated_at: 'Wed Jul 30 2016 18:17:22 GMT+0200 (CEST)',
id: 1
},
ampResult = ampContentHelper.call(testData1),
amperizeCache = ampContentHelper.__get__('amperizeCache');
ampResult.then(function (rendered) {
should.exist(rendered);
should.exist(amperizeCache);
rendered.string.should.equal(testData1.html);
amperizeCache[1].should.have.property('updated_at', 'Wed Jul 27 2016 18:17:22 GMT+0200 (CEST)');
amperizeCache[1].should.have.property('amp', testData1.html);
// call it again with different values to fetch from Amperize and not from cache
ampResult = ampContentHelper.call(testData2);
ampResult.then(function (rendered) {
should.exist(rendered);
should.exist(amperizeCache);
// it should not have the old value,
amperizeCache[1].should.not.have.property('Wed Jul 30 2016 18:17:22 GMT+0200 (CEST)');
// only the new one
rendered.string.should.equal(testData2.html);
amperizeCache[1].should.have.property('updated_at', 'Wed Jul 30 2016 18:17:22 GMT+0200 (CEST)');
amperizeCache[1].should.have.property('amp', testData2.html);
done();
});
}).catch(done);
});
it('sanitizes remaining and not valid tags', function (done) {
var testData = {
html: '<form<input type="text" placeholder="Hi AMP tester"></form>' +
'<script>some script here</script>' +
'<style> h1 {color:red;} p {color:blue;}</style>',
updated_at: 'Wed Jul 27 2016 18:17:22 GMT+0200 (CEST)',
id: 1
},
ampResult = ampContentHelper.call(testData);
ampResult.then(function (rendered) {
should.exist(rendered);
rendered.string.should.be.equal('');
done();
}).catch(done);
});
it('returns if no html is provided', function (done) {
var testData = {
updated_at: 'Wed Jul 27 2016 18:17:22 GMT+0200 (CEST)',
@ -121,60 +39,156 @@ describe('{{amp_content}} helper', function () {
}).catch(done);
});
it('can transform img tags to amp-img', function (done) {
var testData = {
html: '<img src="https://ghost.org/images/ghost.png" alt="The Ghost Logo" />',
updated_at: 'Wed Jul 27 2016 18:17:22 GMT+0200 (CEST)',
id: 1
},
expectedResult = '<amp-img src="https://ghost.org/images/ghost.png" alt="The Ghost Logo" layout="responsive" width="800" height="400"></amp-img>',
ampResult = ampContentHelper.call(testData);
describe('Cache', function () {
it('can render content from cache', function (done) {
var testData = {
html: 'Hello World',
updated_at: 'Wed Jul 27 2016 18:17:22 GMT+0200 (CEST)',
id: 1
},
ampCachedResult,
ampResult = ampContentHelper.call(testData),
amperizeCache = ampContentHelper.__get__('amperizeCache');
ampResult.then(function (rendered) {
should.exist(rendered);
rendered.string.should.equal(expectedResult);
done();
}).catch(done);
ampResult.then(function (rendered) {
should.exist(rendered);
should.exist(amperizeCache);
rendered.string.should.equal(testData.html);
amperizeCache[1].should.have.property('updated_at', 'Wed Jul 27 2016 18:17:22 GMT+0200 (CEST)');
amperizeCache[1].should.have.property('amp', testData.html);
// call it again, to make it fetch from cache
ampCachedResult = ampContentHelper.call(testData);
ampCachedResult.then(function (rendered) {
should.exist(rendered);
should.exist(amperizeCache);
amperizeCache[1].should.have.property('updated_at', 'Wed Jul 27 2016 18:17:22 GMT+0200 (CEST)');
amperizeCache[1].should.have.property('amp', testData.html);
done();
});
}).catch(done);
});
it('fetches new AMP HTML if post was changed', function (done) {
var testData1 = {
html: 'Hello World',
updated_at: 'Wed Jul 27 2016 18:17:22 GMT+0200 (CEST)',
id: 1
},
testData2 = {
html: 'Hello Ghost',
updated_at: 'Wed Jul 30 2016 18:17:22 GMT+0200 (CEST)',
id: 1
},
ampResult = ampContentHelper.call(testData1),
amperizeCache = ampContentHelper.__get__('amperizeCache');
ampResult.then(function (rendered) {
should.exist(rendered);
should.exist(amperizeCache);
rendered.string.should.equal(testData1.html);
amperizeCache[1].should.have.property('updated_at', 'Wed Jul 27 2016 18:17:22 GMT+0200 (CEST)');
amperizeCache[1].should.have.property('amp', testData1.html);
// call it again with different values to fetch from Amperize and not from cache
ampResult = ampContentHelper.call(testData2);
ampResult.then(function (rendered) {
should.exist(rendered);
should.exist(amperizeCache);
// it should not have the old value,
amperizeCache[1].should.not.have.property('Wed Jul 30 2016 18:17:22 GMT+0200 (CEST)');
// only the new one
rendered.string.should.equal(testData2.html);
amperizeCache[1].should.have.property('updated_at', 'Wed Jul 30 2016 18:17:22 GMT+0200 (CEST)');
amperizeCache[1].should.have.property('amp', testData2.html);
done();
});
}).catch(done);
});
});
it('can transform audio tags to amp-audio', function (done) {
var testData = {
html: '<audio controls="controls" width="auto" height="50" autoplay="mobile">Your browser does not support the <code>audio</code> element.<source src="foo.wav" type="audio/wav"></audio>' +
'<audio src="http://foo.ogg"><track kind="captions" src="http://foo.en.vtt" srclang="en" label="English"><track kind="captions" src="http://foo.sv.vtt" srclang="sv" label="Svenska"></audio>',
updated_at: 'Wed Jul 27 2016 18:17:22 GMT+0200 (CEST)',
id: 1
},
expectedResult = '<amp-audio controls="controls" width="auto" height="50" autoplay="mobile">Your browser does not support the <code>audio</code> element.<source src="foo.wav" type="audio/wav" /></amp-audio>' +
'<amp-audio src="https://foo.ogg"><track kind="captions" src="https://foo.en.vtt" srclang="en" label="English" /><track kind="captions" src="https://foo.sv.vtt" srclang="sv" label="Svenska" /></amp-audio>',
ampResult = ampContentHelper.call(testData);
describe('Transforms and sanitizes HTML', function () {
beforeEach(function () {
configUtils.set({url: 'https://my-awesome-blog.com/'});
});
ampResult.then(function (rendered) {
should.exist(rendered);
rendered.string.should.equal(expectedResult);
done();
}).catch(done);
});
afterEach(function () {
ampContentHelper.__set__('amperizeCache', {});
configUtils.restore();
});
it('can handle incomplete HTML tags', function (done) {
var testData = {
html: '<img><///img>',
updated_at: 'Wed Jul 27 2016 18:17:22 GMT+0200 (CEST)',
id: 1
},
ampResult = ampContentHelper.call(testData),
sanitizedHTML,
ampedHTML;
it('can transform img tags to amp-img', function (done) {
var testData = {
html: '<img src="/content/images/ghost.png" alt="The Ghost Logo" />',
updated_at: 'Wed Jul 27 2016 18:17:22 GMT+0200 (CEST)',
id: 1
},
expectedResult = '<amp-img src="https://my-awesome-blog.com/content/images/ghost.png" alt="The Ghost Logo" width="600" height="400" layout="responsive"></amp-img>',
ampResult = ampContentHelper.call(testData);
ampResult.then(function (rendered) {
sanitizedHTML = ampContentHelper.__get__('cleanHTML');
ampedHTML = ampContentHelper.__get__('ampHTML');
should.exist(rendered);
rendered.string.should.equal('');
should.exist(ampedHTML);
ampedHTML.should.be.equal('<img>');
should.exist(sanitizedHTML);
sanitizedHTML.should.be.equal('');
done();
}).catch(done);
ampResult.then(function (rendered) {
should.exist(rendered);
rendered.string.should.equal(expectedResult);
done();
}).catch(done);
});
it('can transform audio tags to amp-audio', function (done) {
var testData = {
html: '<audio controls="controls" width="auto" height="50" autoplay="mobile">Your browser does not support the <code>audio</code> element.<source src="https://audio.com/foo.wav" type="audio/wav"></audio>' +
'<audio src="http://audio.com/foo.ogg"><track kind="captions" src="http://audio.com/foo.en.vtt" srclang="en" label="English"><track kind="captions" src="http://audio.com/foo.sv.vtt" srclang="sv" label="Svenska"></audio>',
updated_at: 'Wed Jul 27 2016 18:17:22 GMT+0200 (CEST)',
id: 1
},
expectedResult = '<amp-audio controls="controls" width="auto" height="50" autoplay="mobile">Your browser does not support the <code>audio</code> element.<source src="https://audio.com/foo.wav" type="audio/wav" /></amp-audio>' +
'<amp-audio src="https://audio.com/foo.ogg"><track kind="captions" src="https://audio.com/foo.en.vtt" srclang="en" label="English" /><track kind="captions" src="https://audio.com/foo.sv.vtt" srclang="sv" label="Svenska" /></amp-audio>',
ampResult = ampContentHelper.call(testData);
ampResult.then(function (rendered) {
should.exist(rendered);
rendered.string.should.equal(expectedResult);
done();
}).catch(done);
});
it('can handle incomplete HTML tags', function (done) {
var testData = {
html: '<img><///img>',
updated_at: 'Wed Jul 27 2016 18:17:22 GMT+0200 (CEST)',
id: 1
},
ampResult = ampContentHelper.call(testData),
sanitizedHTML,
ampedHTML;
ampResult.then(function (rendered) {
sanitizedHTML = ampContentHelper.__get__('cleanHTML');
ampedHTML = ampContentHelper.__get__('ampHTML');
should.exist(rendered);
rendered.string.should.equal('');
should.exist(ampedHTML);
ampedHTML.should.be.equal('<img>');
should.exist(sanitizedHTML);
sanitizedHTML.should.be.equal('');
done();
}).catch(done);
});
it('sanitizes remaining and not valid tags', function (done) {
var testData = {
html: '<form<input type="text" placeholder="Hi AMP tester"></form>' +
'<script>some script here</script>' +
'<style> h1 {color:red;} p {color:blue;}</style>',
updated_at: 'Wed Jul 27 2016 18:17:22 GMT+0200 (CEST)',
id: 1
},
ampResult = ampContentHelper.call(testData);
ampResult.then(function (rendered) {
should.exist(rendered);
rendered.string.should.be.equal('');
done();
}).catch(done);
});
});
});

View file

@ -26,7 +26,7 @@
"node": "~0.10.0 || ~0.12.0 || ^4.2.0"
},
"dependencies": {
"amperize": "0.3.0",
"amperize": "https://github.com/aileencgn/amperize#fixed-layout-for-small-images",
"archiver": "1.0.1",
"bcryptjs": "2.3.0",
"bluebird": "3.4.1",