@aemforms/af-formatters 0.22.25 → 0.22.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,260 @@
1
+ /*************************************************************************
2
+ * ADOBE CONFIDENTIAL
3
+ * ___________________
4
+ *
5
+ * Copyright 2022 Adobe
6
+ * All Rights Reserved.
7
+ *
8
+ * NOTICE: All information contained herein is, and remains
9
+ * the property of Adobe and its suppliers, if any. The intellectual
10
+ * and technical concepts contained herein are proprietary to Adobe
11
+ * and its suppliers and are protected by all applicable intellectual
12
+ * property laws, including trade secret and copyright laws.
13
+ * Dissemination of this information or reproduction of this material
14
+ * is strictly forbidden unless prior written permission is obtained
15
+ * from Adobe.
16
+ **************************************************************************/
17
+ /**
18
+ * https://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
19
+ * Credit: https://git.corp.adobe.com/dc/dfl/blob/master/src/patterns/parseDateTimeSkeleton.js
20
+ * Created a separate library to be used elsewhere as well.
21
+ */
22
+ const DATE_TIME_REGEX =
23
+ // eslint-disable-next-line max-len
24
+ /(?:[Eec]{1,6}|G{1,5}|[Qq]{1,5}|(?:[yYur]+|U{1,5})|[ML]{1,5}|d{1,2}|D{1,3}|F{1}|[abB]{1,5}|[hkHK]{1,2}|w{1,2}|W{1}|m{1,2}|s{1,2}|[zZOvV]{1,5}|[zZOvVxX]{1,3}|S{1,3}|'(?:[^']|'')*')|[^a-zA-Z']+/g;
25
+
26
+ export const ShorthandStyles = ["full", "long", "medium", "short"]
27
+
28
+ const testDate = new Date(2000, 2, 1, 2, 3, 4);
29
+
30
+ /**
31
+ * Since the formatted month names are different than standalone month names, we need to identify the correct option
32
+ * to pass for formatting
33
+ * @param value {string} formatted value of the month
34
+ * @param language {string} language in which the month is formatted
35
+ * @param isMediumFormatStyle {boolean} if shorthand style used for formatting was medium
36
+ */
37
+ function deduceMonthOption(value,
38
+ language,
39
+ isMediumFormatStyle) {
40
+
41
+ const formattedMarch = value;
42
+ const longMarch = new Intl.DateTimeFormat(language, {month: 'long'}).formatToParts(testDate)[0].value;
43
+ const shortMarch = new Intl.DateTimeFormat(language, {month: 'short'}).formatToParts(testDate)[0].value;
44
+
45
+ const monthOptions = {
46
+ [longMarch]: 'long',
47
+ [shortMarch]: 'short',
48
+ '03': '2-digit',
49
+ '3': 'numeric'
50
+ }
51
+ if (formattedMarch !== undefined) {
52
+ monthOptions[formattedMarch] = isMediumFormatStyle ? 'short' : 'long'
53
+ }
54
+ return monthOptions[value];
55
+ }
56
+
57
+ export function getSkeleton(skeleton, language) {
58
+ if (ShorthandStyles.find(type => skeleton.includes(type))) {
59
+ const parsed = parseDateStyle(skeleton, language);
60
+ const result = []
61
+ const symbols = {
62
+ month : 'M',
63
+ year : 'Y',
64
+ day : 'd'
65
+ }
66
+ parsed.forEach(([type, option, length]) => {
67
+ if (type in symbols) {
68
+ result.push(Array(length).fill(symbols[type]).join(''))
69
+ } else if (type === 'literal') {
70
+ result.push(option)
71
+ }
72
+ })
73
+ return result.join('');
74
+ }
75
+ return skeleton;
76
+ }
77
+
78
+ /**
79
+ *
80
+ * @param skeleton shorthand style for the date concatenated with shorthand style of time. The
81
+ * Shorthand style for both date and time is one of ['full', 'long', 'medium', 'short'].
82
+ * @param language {string} language to parse the date shorthand style
83
+ * @returns {[*,string][]}
84
+ */
85
+ function parseDateStyle(skeleton, language) {
86
+ const options = {};
87
+ // the skeleton could have two keywords -- one for date, one for time
88
+ const styles = skeleton.split(/\s/).filter(s => s.length);
89
+ options.dateStyle = styles[0];
90
+ if (styles.length > 1) options.timeStyle = styles[1];
91
+
92
+ const testDate = new Date(2000, 2, 1, 2, 3, 4);
93
+ const parts = new Intl.DateTimeFormat(language, options).formatToParts(testDate);
94
+ // oddly, the formatted month name can be different from the standalone month name
95
+ const formattedMarch = parts.find(p => p.type === 'month').value;
96
+ const longMarch = new Intl.DateTimeFormat(language, {month: 'long'}).formatToParts(testDate)[0].value;
97
+ const shortMarch = new Intl.DateTimeFormat(language, {month: 'short'}).formatToParts(testDate)[0].value;
98
+ const result = [];
99
+ parts.forEach(({type, value}) => {
100
+ let option;
101
+ if (type === 'month') {
102
+ option = {
103
+ [formattedMarch]: skeleton === 'medium' ? 'short' : 'long',
104
+ [longMarch]: 'long',
105
+ [shortMarch]: 'short',
106
+ '03': '2-digit',
107
+ '3': 'numeric'
108
+ }[value];
109
+ }
110
+ if (type === 'year') option = {'2000': 'numeric', '00': '2-digit'}[value];
111
+ if (['day', 'hour', 'minute', 'second'].includes(type)) option = value.length === 2 ? '2-digit' : 'numeric';
112
+ if (type === 'literal') option = value;
113
+ if (type === 'dayPeriod') option = 'short';
114
+ result.push([type, option, value.length]);
115
+ });
116
+ return result;
117
+ }
118
+
119
+ /**
120
+ * Parse Date time skeleton into Intl.DateTimeFormatOptions parts
121
+ * Ref: https://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
122
+ */
123
+ export function parseDateTimeSkeleton(skeleton, language) {
124
+ if (ShorthandStyles.find(type => skeleton.includes(type))) {
125
+ return parseDateStyle(skeleton, language);
126
+ }
127
+ const result = [];
128
+ skeleton.replace(DATE_TIME_REGEX, match => {
129
+ const len = match.length;
130
+ switch (match[0]) {
131
+ // Era
132
+ case 'G':
133
+ result.push(['era', len === 4 ? 'long' : len === 5 ? 'narrow' : 'short', len]);
134
+ break;
135
+ // Year
136
+ case 'y':
137
+ result.push(['year', len === 2 ? '2-digit' : 'numeric', len]);
138
+ break;
139
+ case 'Y':
140
+ case 'u':
141
+ case 'U':
142
+ case 'r':
143
+ throw new RangeError(
144
+ '`Y/u/U/r` (year) patterns are not supported, use `y` instead'
145
+ );
146
+ // Quarter
147
+ case 'q':
148
+ case 'Q':
149
+ throw new RangeError('`q/Q` (quarter) patterns are not supported');
150
+ // Month
151
+ case 'M':
152
+ case 'L':
153
+ result.push(['month', ['numeric', '2-digit', 'short', 'long', 'narrow'][len - 1], len]);
154
+ break;
155
+ // Week
156
+ case 'w':
157
+ case 'W':
158
+ throw new RangeError('`w/W` (week) patterns are not supported');
159
+ case 'd':
160
+ result.push(['day', ['numeric', '2-digit'][len - 1], len]);
161
+ break;
162
+ case 'D':
163
+ case 'F':
164
+ case 'g':
165
+ throw new RangeError(
166
+ '`D/F/g` (day) patterns are not supported, use `d` instead'
167
+ );
168
+ // Weekday
169
+ case 'E':
170
+ result.push(['weekday', ['short', 'short', 'short', 'long', 'narrow', 'narrow'][len - 1], len]);
171
+ break;
172
+ case 'e':
173
+ if (len < 4) {
174
+ throw new RangeError('`e..eee` (weekday) patterns are not supported');
175
+ }
176
+ result.push(['weekday', ['short', 'long', 'narrow', 'short'][len - 4], len]);
177
+ break;
178
+ case 'c':
179
+ if (len < 3 || len > 5) {
180
+ throw new RangeError('`c, cc, cccccc` (weekday) patterns are not supported');
181
+ }
182
+ result.push(['weekday', ['short', 'long', 'narrow', 'short'][len - 3], len]);
183
+ break;
184
+ // Period
185
+ case 'a': // AM, PM
186
+ result.push(['hour12', true, 1]);
187
+ break;
188
+ case 'b': // am, pm, noon, midnight
189
+ case 'B': // flexible day periods
190
+ throw new RangeError(
191
+ '`b/B` (period) patterns are not supported, use `a` instead'
192
+ );
193
+ // Hour
194
+ case 'h':
195
+ result.push(['hourCycle', 'h12']);
196
+ result.push(['hour', ['numeric', '2-digit'][len - 1], len]);
197
+ break;
198
+ case 'H':
199
+ result.push(['hourCycle', 'h23', 1]);
200
+ result.push(['hour', ['numeric', '2-digit'][len - 1], len]);
201
+ break;
202
+ case 'K':
203
+ result.push(['hourCycle', 'h11', 1]);
204
+ result.push(['hour', ['numeric', '2-digit'][len - 1], len]);
205
+ break;
206
+ case 'k':
207
+ result.push(['hourCycle', 'h24', 1]);
208
+ result.push(['hour', ['numeric', '2-digit'][len - 1], len]);
209
+ break;
210
+ case 'j':
211
+ case 'J':
212
+ case 'C':
213
+ throw new RangeError(
214
+ '`j/J/C` (hour) patterns are not supported, use `h/H/K/k` instead'
215
+ );
216
+ // Minute
217
+ case 'm':
218
+ result.push(['minute', ['numeric', '2-digit'][len - 1], len]);
219
+ break;
220
+ // Second
221
+ case 's':
222
+ result.push(['second', ['numeric', '2-digit'][len - 1], len]);
223
+ break;
224
+ case 'S':
225
+ result.push(['fractionalSecondDigits', len, len]);
226
+ break;
227
+ case 'A':
228
+ throw new RangeError(
229
+ '`S/A` (millisecond) patterns are not supported, use `s` instead'
230
+ );
231
+ // Zone
232
+ case 'O': // timeZone GMT-8 or GMT-08:00
233
+ result.push(['timeZoneName', len < 4 ? 'shortOffset' : 'longOffset', len]);
234
+ result.push(['x-timeZoneName', len < 4 ? 'O' : 'OOOO', len]);
235
+ break;
236
+ case 'X': // 1, 2, 3, 4: The ISO8601 varios formats
237
+ case 'x': // 1, 2, 3, 4: The ISO8601 varios formats
238
+ case 'Z': // 1..3, 4, 5: The ISO8601 varios formats
239
+ // Z, ZZ, ZZZ should produce -0800
240
+ // ZZZZ should produce GMT-08:00
241
+ // ZZZZZ should produce -8:00 or -07:52:58
242
+ result.push(['timeZoneName', 'longOffset', 1]);
243
+ result.push(['x-timeZoneName', match, 1]);
244
+ break;
245
+ case 'z': // 1..3, 4: specific non-location format
246
+ case 'v': // 1, 4: generic non-location format
247
+ case 'V': // 1, 2, 3, 4: time zone ID or city
248
+ throw new RangeError(
249
+ 'z/v/V` (timeZone) patterns are not supported, use `X/x/Z/O` instead'
250
+ );
251
+ case '\'':
252
+ result.push(['literal', match.slice(1, -1).replace(/''/g, '\''), -1]);
253
+ break;
254
+ default:
255
+ result.push(['literal', match, -1]);
256
+ }
257
+ return '';
258
+ });
259
+ return result;
260
+ }
@@ -0,0 +1,20 @@
1
+ /*************************************************************************
2
+ * ADOBE CONFIDENTIAL
3
+ * ___________________
4
+ *
5
+ * Copyright 2022 Adobe
6
+ * All Rights Reserved.
7
+ *
8
+ * NOTICE: All information contained herein is, and remains
9
+ * the property of Adobe and its suppliers, if any. The intellectual
10
+ * and technical concepts contained herein are proprietary to Adobe
11
+ * and its suppliers and are protected by all applicable intellectual
12
+ * property laws, including trade secret and copyright laws.
13
+ * Dissemination of this information or reproduction of this material
14
+ * is strictly forbidden unless prior written permission is obtained
15
+ * from Adobe.
16
+ **************************************************************************/
17
+
18
+ import { parseDate, formatDate } from './DateParser.js';
19
+ import {getSkeleton} from "./SkeletonParser.js";
20
+ export {parseDate, formatDate, getSkeleton}
@@ -0,0 +1,36 @@
1
+ import {parseDate, formatDate, getSkeleton as parseDateSkeleton} from "./date/index.js";
2
+ import {parseNumber, formatNumber} from "./number/NumberParser.js"
3
+
4
+ const getCategory = function (skeleton) {
5
+ const chkCategory = skeleton?.match(/^(?:(num|date)\|)?(.+)/);
6
+ return [chkCategory?.[1], chkCategory?.[2]]
7
+ }
8
+
9
+ export const format = function (value, locale, skeleton, timezone) {
10
+ const [category, skelton] = getCategory(skeleton)
11
+ switch (category) {
12
+ case 'date':
13
+ if (!(value instanceof Date)) {
14
+ value = new Date(value)
15
+ }
16
+ return formatDate(value, locale, skelton, timezone)
17
+ case 'num':
18
+ return formatNumber(value, locale, skelton)
19
+ default:
20
+ throw `unable to deduce the format. The skeleton should be date|<format> for date formats and num|<format> for numbers`
21
+ }
22
+ }
23
+
24
+ export const parse = function (value, locale, skeleton, timezone) {
25
+ const [category, skelton] = getCategory(skeleton)
26
+ switch (category) {
27
+ case 'date':
28
+ return parseDate(value, locale, skelton, timezone)
29
+ case 'number':
30
+ return parseNumber(value, locale, skelton)
31
+ default:
32
+ throw `unable to deduce the format. The skeleton should be date|<format> for date formats and num|<format> for numbers`
33
+ }
34
+ }
35
+
36
+ export {parseDate, formatDate, parseDateSkeleton, parseNumber, formatNumber}
@@ -0,0 +1,81 @@
1
+ import {parseNumberSkeleton} from "./SkeletonParser.js";
2
+
3
+ export function formatNumber(numberValue, language, skeletn) {
4
+ if (!skeletn) return numberValue
5
+ language = language || "en"
6
+ const {options, order} = parseNumberSkeleton(skeletn, language);
7
+ return new Intl.NumberFormat(language, options).format(numberValue);
8
+ }
9
+
10
+ function getMetaInfo(language, skel) {
11
+ const parts = {};
12
+ // gather digits and radix symbol
13
+ let options = new Intl.NumberFormat(language, {style:'decimal', useGrouping:false}).formatToParts(9876543210.1);
14
+ parts.digits = options.find(p => p.type === 'integer').value.split('').reverse();
15
+ parts.decimal = options.find(p => p.type === 'decimal').value;
16
+
17
+ // extract type values from the parts
18
+ const gather = type => {
19
+ const find = options.find(p => p.type === type);
20
+ if (find) parts[type] = find.value;
21
+ };
22
+ // now gather the localized parts that correspond to the provided skeleton.
23
+ const parsed = parseNumberSkeleton(skel);
24
+ const nf = new Intl.NumberFormat(language, parsed);
25
+ options = nf.formatToParts(-987654321);
26
+ gather('group');
27
+ gather('minusSign');
28
+ gather('percentSign');
29
+ // it's possible to have multiple currency representations in a single value
30
+ parts.currency = options.filter(p => p.type === 'currency').map(p => p.value);
31
+ // collect all literals. Most likely a literal is an accounting bracket
32
+ parts.literal = options.filter(p => p.type === 'literal').map(p => p.value);
33
+ options = nf.formatToParts(987654321);
34
+ gather('plusSign');
35
+ gather('exponentSeparator');
36
+ gather('unit');
37
+ return parts;
38
+ }
39
+
40
+ export function parseNumber(numberString, language, skel) {
41
+ try {
42
+ // factor will be updated to reflect: negative, percent, exponent etc.
43
+ let factor = 1;
44
+ let number = numberString;
45
+ const meta = getMetaInfo(language, skel);
46
+ if (meta.group) number = number.replaceAll(meta.group, '');
47
+ number = number.replace(meta.decimal, '.');
48
+ if (meta.unit) number = number.replaceAll(meta.unit, '');
49
+ if (meta.minusSign && number.includes(meta.minusSign)) {
50
+ number = number.replace(meta.minusSign, '');
51
+ factor *= -1;
52
+ }
53
+ if (meta.percentSign && number.includes(meta.percentSign)) {
54
+ factor = factor/100;
55
+ number = number.replace(meta.percentSign, '');
56
+ }
57
+ meta.currency.forEach(currency => number = number.replace(currency, ''));
58
+ meta.literal.forEach(literal => {
59
+ if (number.includes(literal)) {
60
+ if (literal === '(') factor = factor * -1;
61
+ number = number.replace(literal, '');
62
+ }
63
+ });
64
+ if (meta.plusSign) number = number.replace(meta.plusSign, '');
65
+ if (meta.exponentSeparator) {
66
+ let e;
67
+ [number, e] = number.split(meta.exponentSeparator);
68
+ factor = factor * Math.pow(10, e);
69
+ }
70
+ const result = factor * number;
71
+ return isNaN(result) ? numberString : result;
72
+ } catch (e) {
73
+ console.dir(e);
74
+ return numberString;
75
+ }
76
+ }
77
+
78
+ export function parseDefaultNumber(numberString, language) {
79
+ const currency = currencies[language] || 'USD';
80
+ return parseNumber(numberString, language, `currency/${currency}`);
81
+ }
@@ -0,0 +1,172 @@
1
+ import {getCurrency} from "./currencies.js"
2
+
3
+ const NUMBER_REGEX =
4
+ // eslint-disable-next-line max-len
5
+ /(?:[#]+|[@]+(?:#+)?|[0]+|[,]|[.]|[-]|[+]|[%]|[¤]{1,4}(?:\/([a-zA-Z]{3}))?|[;]|[K]{1,2}|E{1,2}[+]?|'(?:[^']|'')*')|[^a-zA-Z']+/g;
6
+
7
+ const options = {
8
+ compactDisplay : ['short', 'long'], //valid only when notation is compact
9
+ currency: '', // must be provided if the style is currency
10
+ currencyDisplay: ["symbol", 'narrowSymbol', 'code', 'name'],
11
+ currencySign : ['accounting', 'standard'],
12
+ localeMatcher : ['lookup', 'best fit'],
13
+ notation : ['standard', 'scientific', 'engineering', 'compact'],
14
+ numberingSystem :'' ,
15
+ signDisplay : ['auto', 'always', 'exceptZero', 'negative', 'never'],
16
+ style : ['decimal', 'currency', 'percent', 'unit'],
17
+ unit: '', //https://tc39.es/proposal-unified-intl-numberformat/section6/locales-currencies-tz_proposed_out.html#sec-issanctionedsimpleunitidentifier
18
+ unitDisplay : ['long', 'short', 'narrow'],
19
+ useGrouping : ['always', 'auto', 'min2', false, true],
20
+ roundingMode : '',
21
+ roundingPriority : '',
22
+ roundingIncrement : '',
23
+ trailingZeroDisplay : ['auto', 'stripIfInteger'],
24
+ minimumIntegerDigits : '',
25
+ minimumFractionDigits : '',
26
+ maximumFractionDigits : '',
27
+ minimumSignificantDigits : '',
28
+ maximumSignificantDigits : ''
29
+ }
30
+ const supportedUnits = ['acre', 'bit', 'byte', 'celsius', 'centimeter', 'day',
31
+ 'degree', 'fahrenheit', 'fluid-ounce', 'foot', 'gallon', 'gigabit',
32
+ 'gigabyte', 'gram', 'hectare', 'hour', 'inch', 'kilobit', 'kilobyte',
33
+ 'kilogram', 'kilometer', 'liter', 'megabit', 'megabyte', 'meter', 'mile',
34
+ 'mile-scandinavian', 'milliliter', 'millimeter', 'millisecond', 'minute', 'month',
35
+ 'ounce', 'percent', 'petabyte', 'pound', 'second', 'stone', 'terabit', 'terabyte', 'week', 'yard', 'year'].join('|')
36
+ export const ShorthandStyles = [/^currency(?:\/([a-zA-Z]{3}))?$/, /^decimal$/, /^integer$/, /^percent$/, new RegExp(`^unit\/(${supportedUnits})$`)]
37
+
38
+
39
+ export function parseNumberSkeleton(skeleton, language) {
40
+ const options = {}
41
+ const order = [];
42
+ let match, index
43
+ for (index = 0; index < ShorthandStyles.length && match == null; index++) {
44
+ match = ShorthandStyles[index].exec(skeleton)
45
+ }
46
+ if (match) {
47
+ switch(index) {
48
+ case 1:
49
+ options.style = 'currency'
50
+ options.currencyDisplay = 'narrowSymbol'
51
+ if (match[1]) {
52
+ options.currency = match[1]
53
+ } else {
54
+ options.currency = getCurrency(language)
55
+ }
56
+ break;
57
+ case 2:
58
+ const defaultOptions = new Intl.NumberFormat(language, {}).resolvedOptions();
59
+ options.minimumFractionDigits = options.minimumFractionDigits || 2;
60
+ break;
61
+ case 3:
62
+ options.minimumFractionDigits = 0;
63
+ options.maximumFractionDigits = 0;
64
+ break;
65
+ case 4:
66
+ options.style = 'percent'
67
+ break;
68
+ case 5:
69
+ options.style = "unit";
70
+ options.unitDisplay = "long";
71
+ options.unit = match[1];
72
+ break;
73
+ }
74
+ return {
75
+ options,
76
+ order
77
+ }
78
+ }
79
+ options.useGrouping = false
80
+ options.minimumIntegerDigits = 1
81
+ options.maximumFractionDigits = 0
82
+ options.minimumFractionDigits = 0
83
+ skeleton.replace(NUMBER_REGEX, (match, offset) => {
84
+ const len = match.length;
85
+ switch(match[0]) {
86
+ case '#':
87
+ order.push(['digit', len])
88
+ if (options?.decimal === true) {
89
+ options.maximumFractionDigits = options.minimumFractionDigits + len
90
+ }
91
+ break;
92
+ case '@':
93
+ if (options?.minimumSignificantDigits) {
94
+ throw "@ symbol should occur together"
95
+ }
96
+ order.push(['@', len])
97
+ options.minimumSignificantDigits = len
98
+ const hashes = match.match(/#+/) || ""
99
+ options.maximumSignificantDigits = len + hashes.length
100
+ order.push(['digit', hashes.length])
101
+ break;
102
+ case ',':
103
+ if (options?.decimal === true) {
104
+ throw "grouping character not supporting for fractions"
105
+ }
106
+ order.push(['group', 1])
107
+ options.useGrouping = 'auto';
108
+ break;
109
+ case '.':
110
+ if (options?.decimal) {
111
+ console.error("only one decimal symbol is allowed");
112
+ } else {
113
+ order.push(['decimal', 1])
114
+ options.decimal = true;
115
+ }
116
+ break;
117
+ case '0':
118
+ order.push('0', len)
119
+ if(options.minimumSignificantDigits || options.maximumSignificantDigits) {
120
+ throw "0 is not supported with @"
121
+ }
122
+ if (options?.decimal === true) {
123
+ options.minimumFractionDigits = len;
124
+ } else {
125
+ options.minimumIntegerDigits = len
126
+ }
127
+ break;
128
+ case '-':
129
+ if (offset !== 0) {
130
+ console.error("sign display is always in the beginning")
131
+ }
132
+ options.signDisplay = 'negative'
133
+ order.push(['signDisplay', 1, '-'])
134
+ break;
135
+ case '+':
136
+ if (offset !== 0 && order[order.length - 1][0] === 'E') {
137
+ console.error("sign display is always in the beginning")
138
+ }
139
+ if (offset === 0) {
140
+ options.signDisplay = 'always'
141
+ }
142
+ order.push(['signDisplay', 1, '+'])
143
+ break;
144
+ case '¤':
145
+ if (offset !== 0 && offset !== skeleton.length - 1) {
146
+ console.error("currency display should be either in the beginning or at the end")
147
+ }
148
+ options.style = 'currency'
149
+ options.currencyDisplay = ['symbol', 'code', 'name', 'narrowSymbol'][len -1]
150
+ options.currency = getCurrency(language)
151
+ order.push(['currency', len])
152
+ break;
153
+ case '%':
154
+ if (offset !== 0 && offset !== skeleton.length - 1) {
155
+ console.error("percent display should be either in the beginning or at the end")
156
+ }
157
+ order.push(['%', 1])
158
+ options.style = 'percent'
159
+ break;
160
+ case 'E':
161
+ order.push(['E', len])
162
+ options.style = ['scientific','engineering'](len - 1)
163
+ break;
164
+ default:
165
+ console.error("unknown chars" + match);
166
+ }
167
+ })
168
+ return {
169
+ options,
170
+ order
171
+ };
172
+ }
@@ -0,0 +1,38 @@
1
+ const currencies = {
2
+ 'da-DK': 'DKK',
3
+ 'de-DE': 'EUR',
4
+ 'en-US': 'USD',
5
+ 'en-GB': 'GBP',
6
+ 'es-ES': 'EUR',
7
+ 'fi-FI': 'EUR',
8
+ 'fr-FR': 'EUR',
9
+ 'it-IT': 'EUR',
10
+ 'ja-JP': 'JPY',
11
+ 'nb-NO': 'NOK',
12
+ 'nl-NL': 'EUR',
13
+ 'pt-BR': 'BRL',
14
+ 'sv-SE': 'SEK',
15
+ 'zh-CN': 'CNY',
16
+ 'zh-TW': 'TWD',
17
+ 'ko-KR': 'KRW',
18
+ 'cs-CZ': 'CZK',
19
+ 'pl-PL': 'PLN',
20
+ 'ru-RU': 'RUB',
21
+ 'tr-TR': 'TRY'
22
+ };
23
+
24
+ const locales = Object.keys(currencies)
25
+
26
+ const getCurrency = function (locale) {
27
+ if (locales.indexOf(locale) > -1) {
28
+ return currencies[locale]
29
+ } else {
30
+ const matchingLocale = locales.find(x => x.startsWith(locale))
31
+ if (matchingLocale) {
32
+ return currencies[matchingLocale]
33
+ }
34
+ }
35
+ return ''
36
+ }
37
+
38
+ export {getCurrency}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aemforms/af-formatters",
3
- "version": "0.22.25",
3
+ "version": "0.22.26",
4
4
  "description": "Formatting Module for Forms Runtime",
5
5
  "author": "Adobe Systems",
6
6
  "license": "Adobe Proprietary",