summaryrefslogtreecommitdiffstats
path: root/web_src/js
diff options
context:
space:
mode:
Diffstat (limited to 'web_src/js')
-rw-r--r--web_src/js/features/formatting.js14
-rw-r--r--web_src/js/index.js5
-rw-r--r--web_src/js/utils.js7
-rw-r--r--web_src/js/utils.test.js14
4 files changed, 38 insertions, 2 deletions
diff --git a/web_src/js/features/formatting.js b/web_src/js/features/formatting.js
new file mode 100644
index 0000000000..a7ee7ec3cf
--- /dev/null
+++ b/web_src/js/features/formatting.js
@@ -0,0 +1,14 @@
+import {prettyNumber} from '../utils.js';
+
+const {lang} = document.documentElement;
+
+export function initFormattingReplacements() {
+ // replace english formatted numbers with locale-specific separators
+ for (const el of document.getElementsByClassName('js-pretty-number')) {
+ const num = Number(el.getAttribute('data-value'));
+ const formatted = prettyNumber(num, lang);
+ if (formatted && formatted !== el.textContent) {
+ el.textContent = formatted;
+ }
+ }
+}
diff --git a/web_src/js/index.js b/web_src/js/index.js
index b6a1aee779..0568da64ae 100644
--- a/web_src/js/index.js
+++ b/web_src/js/index.js
@@ -84,6 +84,11 @@ import {initRepoBranchButton} from './features/repo-branch.js';
import {initCommonOrganization} from './features/common-organization.js';
import {initRepoWikiForm} from './features/repo-wiki.js';
import {initRepoCommentForm, initRepository} from './features/repo-legacy.js';
+import {initFormattingReplacements} from './features/formatting.js';
+
+// Run time-critical code as soon as possible. This is safe to do because this
+// script appears at the end of <body> and rendered HTML is accessible at that point.
+initFormattingReplacements();
// Silence fomantic's error logging when tabs are used without a target content element
$.fn.tab.settings.silent = true;
diff --git a/web_src/js/utils.js b/web_src/js/utils.js
index 67f8f1cc98..f01f2d3b22 100644
--- a/web_src/js/utils.js
+++ b/web_src/js/utils.js
@@ -90,3 +90,10 @@ export function strSubMatch(full, sub) {
}
return res;
}
+
+// pretty-print a number using locale-specific separators, e.g. 1200 -> 1,200
+export function prettyNumber(num, locale = 'en-US') {
+ if (typeof num !== 'number') return '';
+ const {format} = new Intl.NumberFormat(locale);
+ return format(num);
+}
diff --git a/web_src/js/utils.test.js b/web_src/js/utils.test.js
index acf3f1ece3..ba5335e3e4 100644
--- a/web_src/js/utils.test.js
+++ b/web_src/js/utils.test.js
@@ -1,5 +1,5 @@
import {
- basename, extname, isObject, uniq, stripTags, joinPaths, parseIssueHref, strSubMatch,
+ basename, extname, isObject, uniq, stripTags, joinPaths, parseIssueHref, strSubMatch, prettyNumber,
} from './utils.js';
test('basename', () => {
@@ -85,7 +85,6 @@ test('parseIssueHref', () => {
expect(parseIssueHref('')).toEqual({owner: undefined, repo: undefined, type: undefined, index: undefined});
});
-
test('strSubMatch', () => {
expect(strSubMatch('abc', '')).toEqual(['abc']);
expect(strSubMatch('abc', 'a')).toEqual(['', 'a', 'bc']);
@@ -98,3 +97,14 @@ test('strSubMatch', () => {
expect(strSubMatch('aabbcc', 'abc')).toEqual(['', 'a', 'a', 'b', 'b', 'c', 'c']);
expect(strSubMatch('the/directory', 'hedir')).toEqual(['t', 'he', '/', 'dir', 'ectory']);
});
+
+test('prettyNumber', () => {
+ expect(prettyNumber()).toEqual('');
+ expect(prettyNumber(null)).toEqual('');
+ expect(prettyNumber(undefined)).toEqual('');
+ expect(prettyNumber('1200')).toEqual('');
+ expect(prettyNumber(12345678, 'en-US')).toEqual('12,345,678');
+ expect(prettyNumber(12345678, 'de-DE')).toEqual('12.345.678');
+ expect(prettyNumber(12345678, 'be-BE')).toEqual('12 345 678');
+ expect(prettyNumber(12345678, 'hi-IN')).toEqual('1,23,45,678');
+});