mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
Updated default format for date helper to locale-based date string (#12733)
refs https://github.com/TryGhost/Casper/pull/741 closes https://github.com/TryGhost/Team/issues/524 - Use a local-based format as the default format as suggested in https://github.com/TryGhost/Casper/pull/741 - reworked the helper to be easier to read and follow the different use cases - introduced setting and resetting locale in tests via settingsCache and themei18n - updated tests to cover more cases e.g. passing a date, this.published_at and no date - added validation for user inputted dates because they could literally be anything Co-authored-by: Hannah Wolfe <erisds@gmail.com>
This commit is contained in:
parent
226607a203
commit
b4140d4310
3 changed files with 149 additions and 26 deletions
|
@ -5,42 +5,51 @@
|
|||
|
||||
const {SafeString, themeI18n} = require('../services/proxy');
|
||||
const moment = require('moment-timezone');
|
||||
const _ = require('lodash');
|
||||
|
||||
module.exports = function (date, options) {
|
||||
let timezone;
|
||||
module.exports = function (...attrs) {
|
||||
// Options is the last argument
|
||||
const options = attrs.pop();
|
||||
let date;
|
||||
|
||||
if (!options && Object.prototype.hasOwnProperty.call(date, 'hash')) {
|
||||
options = date;
|
||||
date = undefined;
|
||||
timezone = options.data.site.timezone;
|
||||
// If there is any more arguments, date is the first one
|
||||
if (!_.isEmpty(attrs)) {
|
||||
date = attrs.shift();
|
||||
|
||||
// set to published_at by default, if it's available
|
||||
// otherwise, this will print the current date
|
||||
if (this.published_at) {
|
||||
date = moment(this.published_at).tz(timezone).format();
|
||||
}
|
||||
// If there is no date argument & the current context contains published_at use that by default,
|
||||
// else date being undefined means moment will use the current date
|
||||
} else if (this.published_at) {
|
||||
date = this.published_at;
|
||||
}
|
||||
|
||||
// ensure that date is undefined, not null, as that can cause errors
|
||||
date = date === null ? undefined : date;
|
||||
|
||||
const timezone = options.data.site.timezone;
|
||||
const {
|
||||
format = 'MMM DD, YYYY',
|
||||
format = 'll',
|
||||
timeago
|
||||
} = options.hash;
|
||||
|
||||
// ensure that context is undefined, not null, as that can cause errors
|
||||
date = date === null ? undefined : date;
|
||||
timezone = options.data.site.timezone;
|
||||
const timeNow = moment().tz(timezone);
|
||||
// Our date might be user input
|
||||
let testDateInput = Date.parse(date);
|
||||
let dateMoment;
|
||||
if (isNaN(testDateInput) === false) {
|
||||
dateMoment = moment.parseZone(date);
|
||||
} else {
|
||||
dateMoment = timeNow;
|
||||
}
|
||||
|
||||
// i18n: Making dates, including month names, translatable to any language.
|
||||
// Documentation: http://momentjs.com/docs/#/i18n/
|
||||
// Locales: https://github.com/moment/moment/tree/develop/locale
|
||||
const dateMoment = moment(date);
|
||||
dateMoment.locale(themeI18n.locale());
|
||||
|
||||
if (timeago) {
|
||||
date = timezone ? dateMoment.tz(timezone).from(timeNow) : dateMoment.fromNow();
|
||||
date = dateMoment.tz(timezone).from(timeNow);
|
||||
} else {
|
||||
date = timezone ? dateMoment.tz(timezone).format(format) : dateMoment.format(format);
|
||||
date = dateMoment.tz(timezone).format(format);
|
||||
}
|
||||
|
||||
return new SafeString(date);
|
||||
|
|
|
@ -1,11 +1,20 @@
|
|||
const sinon = require('sinon');
|
||||
const should = require('should');
|
||||
|
||||
// Stuff we are testing
|
||||
const helpers = require('../../../core/frontend/helpers');
|
||||
|
||||
const proxy = require('../../../core/frontend/services/proxy');
|
||||
const settingsCache = require('../../../core/server/services/settings/cache');
|
||||
|
||||
const moment = require('moment-timezone');
|
||||
|
||||
describe('{{date}} helper', function () {
|
||||
afterEach(function () {
|
||||
settingsCache.reset();
|
||||
proxy.themeI18n._loadLocale();
|
||||
});
|
||||
|
||||
it('creates properly formatted date strings', function () {
|
||||
const testDates = [
|
||||
'2013-12-31T11:28:58.593+02:00',
|
||||
|
@ -14,7 +23,7 @@ describe('{{date}} helper', function () {
|
|||
'2014-03-01T01:28:58.593+00:00'
|
||||
];
|
||||
|
||||
const timezones = 'Europe/Dublin';
|
||||
const timezone = 'Europe/Dublin';
|
||||
const format = 'MMM Do, YYYY';
|
||||
|
||||
const context = {
|
||||
|
@ -23,16 +32,78 @@ describe('{{date}} helper', function () {
|
|||
},
|
||||
data: {
|
||||
site: {
|
||||
timezone: 'Europe/Dublin'
|
||||
timezone
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let rendered;
|
||||
|
||||
testDates.forEach(function (d) {
|
||||
const rendered = helpers.date.call({published_at: d}, context);
|
||||
rendered = helpers.date.call({published_at: d}, context);
|
||||
|
||||
should.exist(rendered);
|
||||
String(rendered).should.equal(moment(d).tz(timezones).format(format));
|
||||
String(rendered).should.equal(moment(d).tz(timezone).format(format));
|
||||
|
||||
rendered = helpers.date.call({}, d, context);
|
||||
|
||||
should.exist(rendered);
|
||||
String(rendered).should.equal(moment(d).tz(timezone).format(format));
|
||||
});
|
||||
|
||||
// No date falls back to now
|
||||
rendered = helpers.date.call({}, context);
|
||||
should.exist(rendered);
|
||||
String(rendered).should.equal(moment().tz(timezone).format(format));
|
||||
});
|
||||
|
||||
it('creates properly localised date strings', function () {
|
||||
const testDates = [
|
||||
'2013-12-31T23:58:58.593+02:00',
|
||||
'2014-01-01T00:28:58.593+11:00',
|
||||
'2014-11-20T01:28:58.593-04:00',
|
||||
'2014-03-01T01:28:58.593+00:00'
|
||||
];
|
||||
|
||||
const locales = [
|
||||
'en',
|
||||
'en-gb',
|
||||
'de'
|
||||
];
|
||||
|
||||
const timezone = 'Europe/Dublin';
|
||||
const format = 'll';
|
||||
|
||||
const context = {
|
||||
hash: {},
|
||||
data: {
|
||||
site: {
|
||||
timezone
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
locales.forEach(function (l) {
|
||||
settingsCache.set('lang', {value: l});
|
||||
proxy.themeI18n._loadLocale();
|
||||
let rendered;
|
||||
|
||||
testDates.forEach(function (d) {
|
||||
rendered = helpers.date.call({published_at: d}, context);
|
||||
|
||||
should.exist(rendered);
|
||||
String(rendered).should.equal(moment(d).tz(timezone).locale(l).format(format));
|
||||
|
||||
rendered = helpers.date.call({}, d, context);
|
||||
|
||||
should.exist(rendered);
|
||||
String(rendered).should.equal(moment(d).tz(timezone).locale(l).format(format));
|
||||
});
|
||||
|
||||
// No date falls back to now
|
||||
rendered = helpers.date.call({}, context);
|
||||
should.exist(rendered);
|
||||
String(rendered).should.equal(moment().tz(timezone).locale(l).format(format));
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -44,7 +115,7 @@ describe('{{date}} helper', function () {
|
|||
'2014-03-01T01:28:58.593+00:00'
|
||||
];
|
||||
|
||||
const timezones = 'Europe/Dublin';
|
||||
const timezone = 'Europe/Dublin';
|
||||
const timeNow = moment().tz('Europe/Dublin');
|
||||
|
||||
const context = {
|
||||
|
@ -53,16 +124,57 @@ describe('{{date}} helper', function () {
|
|||
},
|
||||
data: {
|
||||
site: {
|
||||
timezone: 'Europe/Dublin'
|
||||
timezone
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let rendered;
|
||||
|
||||
testDates.forEach(function (d) {
|
||||
const rendered = helpers.date.call({published_at: d}, context);
|
||||
rendered = helpers.date.call({published_at: d}, context);
|
||||
|
||||
should.exist(rendered);
|
||||
String(rendered).should.equal(moment(d).tz(timezones).from(timeNow));
|
||||
String(rendered).should.equal(moment(d).tz(timezone).from(timeNow));
|
||||
|
||||
rendered = helpers.date.call({}, d, context);
|
||||
|
||||
should.exist(rendered);
|
||||
String(rendered).should.equal(moment(d).tz(timezone).from(timeNow));
|
||||
});
|
||||
|
||||
// No date falls back to now
|
||||
rendered = helpers.date.call({}, context);
|
||||
should.exist(rendered);
|
||||
String(rendered).should.equal('a few seconds ago');
|
||||
});
|
||||
|
||||
it('ignores an invalid date, defaulting to now', function () {
|
||||
const timezone = 'Europe/Dublin';
|
||||
const timeNow = moment().tz('Europe/Dublin');
|
||||
|
||||
const context = {
|
||||
hash: {
|
||||
timeago: true
|
||||
},
|
||||
data: {
|
||||
site: {
|
||||
timezone
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let invalidDate = 'Fred';
|
||||
let rendered;
|
||||
|
||||
rendered = helpers.date.call({published_at: invalidDate}, context);
|
||||
|
||||
should.exist(rendered);
|
||||
String(rendered).should.equal('a few seconds ago');
|
||||
|
||||
rendered = helpers.date.call({}, invalidDate, context);
|
||||
|
||||
should.exist(rendered);
|
||||
String(rendered).should.equal('a few seconds ago');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,10 +6,12 @@ const proxy = require('../../../core/frontend/services/proxy');
|
|||
describe('{{lang}} helper', function () {
|
||||
beforeEach(function () {
|
||||
settingsCache.set('lang', {value: 'en'});
|
||||
proxy.themeI18n._loadLocale();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
settingsCache.shutdown();
|
||||
proxy.themeI18n._loadLocale();
|
||||
});
|
||||
|
||||
it('returns correct language tag', function () {
|
||||
|
|
Loading…
Add table
Reference in a new issue