diff options
author | Timothy Flynn <trflynn89@pm.me> | 2021-11-15 11:07:41 -0500 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-11-16 00:56:55 +0000 |
commit | fdae323401e907bd824348a3f009ccda232bcdc4 (patch) | |
tree | 322cc4c4da8388dd559a87c8ab3a542ee91cee9d | |
parent | 80b86d20dc1dbe68dea845cce61e679bb5885137 (diff) | |
download | serenity-fdae323401e907bd824348a3f009ccda232bcdc4.zip |
LibJS: Implement compact formatting for Intl.NumberFormat
3 files changed, 117 insertions, 12 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/Intl/NumberFormat.cpp b/Userland/Libraries/LibJS/Runtime/Intl/NumberFormat.cpp index 5c5dcc2a2f..a74c229f63 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/NumberFormat.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/NumberFormat.cpp @@ -945,18 +945,15 @@ Vector<PatternPartition> partition_notation_sub_pattern(NumberFormat& number_for } } // iv. Else if p is equal to "compactSymbol", then - else if (part == "compactSymbol"sv) { - // 1. Let compactSymbol be an ILD string representing exponent in short form, which may depend on x in languages having different plural forms. The implementation must be able to provide this string, or else the pattern would not have a "{compactSymbol}" placeholder. - // 2. Append a new Record { [[Type]]: "compact", [[Value]]: compactSymbol } as the last element of result. - - // FIXME: Implement this when GetNotationSubPattern is fully implemented. - } // v. Else if p is equal to "compactName", then - else if (part == "compactName"sv) { - // 1. Let compactName be an ILD string representing exponent in long form, which may depend on x in languages having different plural forms. The implementation must be able to provide this string, or else the pattern would not have a "{compactName}" placeholder. - // 2. Append a new Record { [[Type]]: "compact", [[Value]]: compactName } as the last element of result. + else if (part == "compactIdentifier"sv) { + // Note: Our implementation combines "compactSymbol" and "compactName" into one field, "compactIdentifier". - // FIXME: Implement this when GetNotationSubPattern is fully implemented. + // 1. Let compactSymbol be an ILD string representing exponent in short form, which may depend on x in languages having different plural forms. The implementation must be able to provide this string, or else the pattern would not have a "{compactSymbol}" placeholder. + auto compact_identifier = number_format.compact_format().compact_identifier; + + // 2. Append a new Record { [[Type]]: "compact", [[Value]]: compactSymbol } as the last element of result. + result.append({ "compact"sv, compact_identifier }); } // vi. Else if p is equal to "scientificSeparator", then else if (part == "scientificSeparator"sv) { @@ -1491,12 +1488,14 @@ Optional<StringView> get_notation_sub_pattern(NumberFormat& number_format, int e } // 8. Else if exponent is not 0, then else if (exponent != 0) { - // FIXME: Implement this. - // a. Assert: notation is "compact". + VERIFY(notation == NumberFormat::Notation::Compact); + // b. Let compactDisplay be numberFormat.[[CompactDisplay]]. // c. Let compactPatterns be notationSubPatterns.[[compact]].[[<compactDisplay>]]. // d. Return compactPatterns.[[<exponent>]]. + if (number_format.has_compact_format()) + return number_format.compact_format().zero_format; } // 9. Else, diff --git a/Userland/Libraries/LibJS/Tests/builtins/Intl/NumberFormat/NumberFormat.prototype.format.js b/Userland/Libraries/LibJS/Tests/builtins/Intl/NumberFormat/NumberFormat.prototype.format.js index 4158eafa2b..54381e9f83 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Intl/NumberFormat/NumberFormat.prototype.format.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Intl/NumberFormat/NumberFormat.prototype.format.js @@ -205,6 +205,54 @@ describe("style=decimal", () => { expect(ar.format(12.34)).toBe("\u0661\u0662"); }); + test("notation=compact, compactDisplay=long", () => { + const en = new Intl.NumberFormat("en", { notation: "compact", compactDisplay: "long" }); + expect(en.format(1)).toBe("1"); + expect(en.format(1200)).toBe("1.2 thousand"); + expect(en.format(1290)).toBe("1.3 thousand"); + expect(en.format(12000)).toBe("12 thousand"); + expect(en.format(12900)).toBe("13 thousand"); + expect(en.format(1200000)).toBe("1.2 million"); + expect(en.format(1290000)).toBe("1.3 million"); + expect(en.format(12000000)).toBe("12 million"); + expect(en.format(12900000)).toBe("13 million"); + + const ar = new Intl.NumberFormat("ar", { notation: "compact", compactDisplay: "long" }); + expect(ar.format(1)).toBe("\u0661"); + expect(ar.format(1200)).toBe("\u0661\u066b\u0662 ألف"); + expect(ar.format(1290)).toBe("\u0661\u066b\u0663 ألف"); + expect(ar.format(12000)).toBe("\u0661\u0662 ألف"); + expect(ar.format(12900)).toBe("\u0661\u0663 ألف"); + expect(ar.format(1200000)).toBe("\u0661\u066b\u0662 مليون"); + expect(ar.format(1290000)).toBe("\u0661\u066b\u0663 مليون"); + expect(ar.format(12000000)).toBe("\u0661\u0662 مليون"); + expect(ar.format(12900000)).toBe("\u0661\u0663 مليون"); + }); + + test("notation=compact, compactDisplay=short", () => { + const en = new Intl.NumberFormat("en", { notation: "compact", compactDisplay: "short" }); + expect(en.format(1)).toBe("1"); + expect(en.format(1200)).toBe("1.2K"); + expect(en.format(1290)).toBe("1.3K"); + expect(en.format(12000)).toBe("12K"); + expect(en.format(12900)).toBe("13K"); + expect(en.format(1200000)).toBe("1.2M"); + expect(en.format(1290000)).toBe("1.3M"); + expect(en.format(12000000)).toBe("12M"); + expect(en.format(12900000)).toBe("13M"); + + const ar = new Intl.NumberFormat("ar", { notation: "compact", compactDisplay: "short" }); + expect(ar.format(1)).toBe("\u0661"); + expect(ar.format(1200)).toBe("\u0661\u066b\u0662\u00a0ألف"); + expect(ar.format(1290)).toBe("\u0661\u066b\u0663\u00a0ألف"); + expect(ar.format(12000)).toBe("\u0661\u0662\u00a0ألف"); + expect(ar.format(12900)).toBe("\u0661\u0663\u00a0ألف"); + expect(ar.format(1200000)).toBe("\u0661\u066b\u0662\u00a0مليون"); + expect(ar.format(1290000)).toBe("\u0661\u066b\u0663\u00a0مليون"); + expect(ar.format(12000000)).toBe("\u0661\u0662\u00a0مليون"); + expect(ar.format(12900000)).toBe("\u0661\u0663\u00a0مليون"); + }); + test("signDisplay=never", () => { const en = new Intl.NumberFormat("en", { signDisplay: "never" }); expect(en.format(1)).toBe("1"); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Intl/NumberFormat/NumberFormat.prototype.formatToParts.js b/Userland/Libraries/LibJS/Tests/builtins/Intl/NumberFormat/NumberFormat.prototype.formatToParts.js index c6cfa7ed63..d787e5ba4b 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Intl/NumberFormat/NumberFormat.prototype.formatToParts.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Intl/NumberFormat/NumberFormat.prototype.formatToParts.js @@ -312,6 +312,64 @@ describe("style=decimal", () => { { type: "exponentInteger", value: "\u0663" }, ]); }); + + test("notation=compact, compactDisplay=long", () => { + const en = new Intl.NumberFormat("en", { notation: "compact", compactDisplay: "long" }); + expect(en.formatToParts(1200)).toEqual([ + { type: "integer", value: "1" }, + { type: "decimal", value: "." }, + { type: "fraction", value: "2" }, + { type: "literal", value: " " }, + { type: "compact", value: "thousand" }, + ]); + expect(en.formatToParts(12900000)).toEqual([ + { type: "integer", value: "13" }, + { type: "literal", value: " " }, + { type: "compact", value: "million" }, + ]); + + const ar = new Intl.NumberFormat("ar", { notation: "compact", compactDisplay: "long" }); + expect(ar.formatToParts(1200)).toEqual([ + { type: "integer", value: "\u0661" }, + { type: "decimal", value: "\u066b" }, + { type: "fraction", value: "\u0662" }, + { type: "literal", value: " " }, + { type: "compact", value: "ألف" }, + ]); + expect(ar.formatToParts(12900000)).toEqual([ + { type: "integer", value: "\u0661\u0663" }, + { type: "literal", value: " " }, + { type: "compact", value: "مليون" }, + ]); + }); + + test("notation=compact, compactDisplay=short", () => { + const en = new Intl.NumberFormat("en", { notation: "compact", compactDisplay: "short" }); + expect(en.formatToParts(1200)).toEqual([ + { type: "integer", value: "1" }, + { type: "decimal", value: "." }, + { type: "fraction", value: "2" }, + { type: "compact", value: "K" }, + ]); + expect(en.formatToParts(12900000)).toEqual([ + { type: "integer", value: "13" }, + { type: "compact", value: "M" }, + ]); + + const ar = new Intl.NumberFormat("ar", { notation: "compact", compactDisplay: "short" }); + expect(ar.formatToParts(1200)).toEqual([ + { type: "integer", value: "\u0661" }, + { type: "decimal", value: "\u066b" }, + { type: "fraction", value: "\u0662" }, + { type: "literal", value: "\u00a0" }, + { type: "compact", value: "ألف" }, + ]); + expect(ar.formatToParts(12900000)).toEqual([ + { type: "integer", value: "\u0661\u0663" }, + { type: "literal", value: "\u00a0" }, + { type: "compact", value: "مليون" }, + ]); + }); }); describe("style=percent", () => { |