mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-20 17:32:15 +03:00
4f7324f1c0
refs https://github.com/TryGhost/Team/issues/449 - Once we deprecate site.lang use in favor of site.locale this helper will need inspection for potentially breaking change. Left a note to come back to it once it's time
105 lines
3.1 KiB
JavaScript
105 lines
3.1 KiB
JavaScript
// # {{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 || {};
|
|
// NOTE: potentially breaking place once site.lang is removed in favor of site.locale
|
|
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;
|
|
};
|