Ghost/core/frontend/helpers/price.js

104 lines
3.0 KiB
JavaScript
Raw Normal View History

// # {{price}} helper
//
// Usage: `{{price 2100}}`
// Usage: `{{price plan}}`
// Usage: `{{price plan numberFormat="long"}}`
// Usage: `{{price plan currencyFormat="code"}}`
// Usage: `{{price plan currencyFormat="name"}}`
// Usage: `{{price 500 currency="USD"}}`
// Usage: `{{price currency="USD"}}`
//
// Returns amount equal to the dominant denomintation of the currency.
// For example, if 2100 is passed, it will return 21.
const errors = require('@tryghost/errors');
const tpl = require('@tryghost/tpl');
const _ = require('lodash');
const messages = {
attrIsRequired: 'Attribute is required e.g. {{price plan.amount}}',
attrMustBeNumeric: 'Attribute value should be a number'
};
function formatter({amount, currency, numberFormat = 'short', currencyFormat = 'symbol', locale}) {
const formatterOptions = {
style: 'currency',
currency: currency,
currencyDisplay: currencyFormat
};
if (numberFormat === 'short') {
formatterOptions.minimumFractionDigits = 0;
}
if (_.isNumber(amount)) {
return new Intl.NumberFormat(locale, formatterOptions).format(amount);
} else {
const val = new Intl.NumberFormat('en', {
style: 'currency',
currency,
currencyDisplay: 'symbol',
minimumFractionDigits: 0,
maximumFractionDigits: 0
}).format(0);
return val.replace(/[\d\s.,]/g, '');
}
}
module.exports = function price(planOrAmount, options) {
let plan;
let amount;
if (arguments.length === 1) {
options = planOrAmount;
}
if (arguments.length === 2) {
if (_.isNumber(planOrAmount)) {
amount = planOrAmount;
} else if (_.isObject(planOrAmount)) {
plan = planOrAmount;
}
}
options = options || {};
options.hash = options.hash || {};
const {currency, numberFormat = 'short', currencyFormat = 'symbol', locale = _.get(options, 'data.site.lang', 'en')} = options.hash;
if (plan) {
return formatter({
amount: plan.amount && (plan.amount / 100),
currency: currency || plan.currency,
currencyFormat,
numberFormat,
locale
});
}
if (currency) {
return formatter({
amount: amount && (amount / 100),
currency: currency,
currencyFormat,
numberFormat,
locale
});
}
// CASE: if no amount is passed, e.g. `{{price}}` we throw an error
if (arguments.length < 2) {
throw new errors.IncorrectUsageError({
message: tpl(messages.attrIsRequired)
});
}
// CASE: if amount is passed, but it is undefined we throw an error
if (amount === undefined) {
throw new errors.IncorrectUsageError({
message: tpl(messages.attrIsRequired)
});
}
if (!_.isNumber(amount)) {
throw new errors.IncorrectUsageError({
message: tpl(messages.attrMustBeNumeric)
});
}
return amount / 100;
};