Skip to content

Commit

Permalink
Add support for unit in NumberFormat (#11839)
Browse files Browse the repository at this point in the history
* Add support for `unit` in `NumberFormat`

* Add test for `unit` in `NumberFormat`

* Update docs for `unit` NumberFormat
  • Loading branch information
varna authored May 17, 2022
1 parent b51ea41 commit 3228854
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 4 deletions.
26 changes: 23 additions & 3 deletions src/style-spec/expression/definitions/number_format.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ declare class Intl$NumberFormat {
}

type NumberFormatOptions = {
style?: 'decimal' | 'currency' | 'percent';
style?: 'decimal' | 'currency' | 'percent' | 'unit';
currency?: null | string;
unit?: null | string;
minimumFractionDigits?: null | string;
maximumFractionDigits?: null | string;
};
Expand All @@ -39,18 +40,21 @@ export default class NumberFormat implements Expression {
number: Expression;
locale: Expression | null; // BCP 47 language tag
currency: Expression | null; // ISO 4217 currency code, required if style=currency
unit: Expression | null; // Simple units sanctioned for use in ECMAScript, required if style=unit. https://tc39.es/proposal-unified-intl-numberformat/section6/locales-currencies-tz_proposed_out.html#sec-issanctionedsimpleunitidentifier
minFractionDigits: Expression | null; // Default 0
maxFractionDigits: Expression | null; // Default 3

constructor(number: Expression,
locale: Expression | null,
currency: Expression | null,
unit: Expression | null,
minFractionDigits: Expression | null,
maxFractionDigits: Expression | null) {
this.type = StringType;
this.number = number;
this.locale = locale;
this.currency = currency;
this.unit = unit;
this.minFractionDigits = minFractionDigits;
this.maxFractionDigits = maxFractionDigits;
}
Expand Down Expand Up @@ -78,6 +82,12 @@ export default class NumberFormat implements Expression {
if (!currency) return null;
}

let unit = null;
if (options['unit']) {
unit = context.parse(options['unit'], 1, StringType);
if (!unit) return null;
}

let minFractionDigits = null;
if (options['min-fraction-digits']) {
minFractionDigits = context.parse(options['min-fraction-digits'], 1, NumberType);
Expand All @@ -90,14 +100,18 @@ export default class NumberFormat implements Expression {
if (!maxFractionDigits) return null;
}

return new NumberFormat(number, locale, currency, minFractionDigits, maxFractionDigits);
return new NumberFormat(number, locale, currency, unit, minFractionDigits, maxFractionDigits);
}

evaluate(ctx: EvaluationContext): string {
return new Intl.NumberFormat(this.locale ? this.locale.evaluate(ctx) : [],
{
style: this.currency ? "currency" : "decimal",
style:
(this.currency && "currency") ||
(this.unit && "unit") ||
"decimal",
currency: this.currency ? this.currency.evaluate(ctx) : undefined,
unit: this.unit ? this.unit.evaluate(ctx) : undefined,
minimumFractionDigits: this.minFractionDigits ? this.minFractionDigits.evaluate(ctx) : undefined,
maximumFractionDigits: this.maxFractionDigits ? this.maxFractionDigits.evaluate(ctx) : undefined,
}).format(this.number.evaluate(ctx));
Expand All @@ -111,6 +125,9 @@ export default class NumberFormat implements Expression {
if (this.currency) {
fn(this.currency);
}
if (this.unit) {
fn(this.unit);
}
if (this.minFractionDigits) {
fn(this.minFractionDigits);
}
Expand All @@ -131,6 +148,9 @@ export default class NumberFormat implements Expression {
if (this.currency) {
options['currency'] = this.currency.serialize();
}
if (this.unit) {
options['unit'] = this.unit.serialize();
}
if (this.minFractionDigits) {
options['min-fraction-digits'] = this.minFractionDigits.serialize();
}
Expand Down
2 changes: 1 addition & 1 deletion src/style-spec/reference/v8.json
Original file line number Diff line number Diff line change
Expand Up @@ -3046,7 +3046,7 @@
}
},
"number-format": {
"doc": "Converts the input number into a string representation using the providing formatting rules. If set, the `locale` argument specifies the locale to use, as a BCP 47 language tag. If set, the `currency` argument specifies an ISO 4217 code to use for currency-style formatting. If set, the `min-fraction-digits` and `max-fraction-digits` arguments specify the minimum and maximum number of fractional digits to include.",
"doc": "Converts the input number into a string representation using the providing formatting rules. If set, the `locale` argument specifies the locale to use, as a BCP 47 language tag. If set, the `currency` argument specifies an ISO 4217 code to use for currency-style formatting. If set, the `unit` argument specifies a [simple ECMAScript unit](https://tc39.es/proposal-unified-intl-numberformat/section6/locales-currencies-tz_proposed_out.html#sec-issanctionedsimpleunitidentifier) to use for unit-style formatting. If set, the `min-fraction-digits` and `max-fraction-digits` arguments specify the minimum and maximum number of fractional digits to include.",
"group": "Types",
"sdk-support": {
"basic functionality": {
Expand Down
31 changes: 31 additions & 0 deletions test/integration/expression-tests/number-format/unit/test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"expression": [
"number-format",
123456.789,
{
"locale": ["get", "locale"],
"unit": ["get", "unit"]
}
],
"inputs": [
[{}, {"properties": {"locale": "en-US", "unit": "hectare"}}],
[{}, {"properties": {"locale": "en-US", "unit": "acre"}}]
],
"expected": {
"compiled": {
"result": "success",
"isFeatureConstant": false,
"isZoomConstant": true,
"type": "string"
},
"outputs": ["123,456.789 ha", "123,456.789 ac"],
"serialized": [
"number-format",
123456.789,
{
"locale": ["string", ["get", "locale"]],
"unit": ["string", ["get", "unit"]]
}
]
}
}

0 comments on commit 3228854

Please sign in to comment.