diff --git a/client/js/controllers/tags_controller.js b/client/js/controllers/tags_controller.js
index 91330ba4..ef2d94db 100644
--- a/client/js/controllers/tags_controller.js
+++ b/client/js/controllers/tags_controller.js
@@ -185,10 +185,9 @@ class TagsController {
pageController.run({
state: ctx.state,
requestPage: page => {
+ const text = ctx.searchQuery.text;
return api.get(
- '/tags/?query={text}&page={page}&pageSize=50'.format({
- text: ctx.searchQuery.text,
- page: page}));
+ `/tags/?query=${text}&page=${page}&pageSize=50`);
},
clientUrl: '/tags/' + misc.formatSearchQuery({
text: ctx.searchQuery.text, page: '{page}'}),
diff --git a/client/js/controllers/users_controller.js b/client/js/controllers/users_controller.js
index 53f485e8..96d609af 100644
--- a/client/js/controllers/users_controller.js
+++ b/client/js/controllers/users_controller.js
@@ -67,10 +67,9 @@ class UsersController {
pageController.run({
state: ctx.state,
requestPage: page => {
+ const text = ctx.searchQuery.text;
return api.get(
- '/users/?query={text}&page={page}&pageSize=30'.format({
- text: ctx.searchQuery.text,
- page: page}));
+ `/users/?query=${text}&page=${page}&pageSize=30`);
},
clientUrl: '/users/' + misc.formatSearchQuery({
text: ctx.searchQuery.text, page: '{page}'}),
diff --git a/client/js/controls/tag_auto_complete_control.js b/client/js/controls/tag_auto_complete_control.js
index 7bb9090c..6bbe8d87 100644
--- a/client/js/controls/tag_auto_complete_control.js
+++ b/client/js/controls/tag_auto_complete_control.js
@@ -1,5 +1,6 @@
'use strict';
+const unindent = require('../util/misc.js').unindent;
const lodash = require('lodash');
const tags = require('../tags.js');
const AutoCompleteControl = require('./auto_complete_control.js');
@@ -26,12 +27,14 @@ class TagAutoCompleteControl extends AutoCompleteControl {
return kv2[1].usages - kv1[1].usages;
})
.map(kv => {
+ const category = kv[1].category;
+ const origName = tags.getOriginalTagName(kv[0]);
+ const usages = kv[1].usages;
return {
- caption:
- '{1} ({2})'.format(
- kv[1].category,
- tags.getOriginalTagName(kv[0]),
- kv[1].usages),
+ caption: unindent`
+
+ ${origName} (${usages})
+ `,
value: kv[0],
};
});
diff --git a/client/js/tags.js b/client/js/tags.js
index 359d997a..09ff9252 100644
--- a/client/js/tags.js
+++ b/client/js/tags.js
@@ -1,7 +1,6 @@
'use strict';
const request = require('superagent');
-const util = require('./util/misc.js');
const events = require('./events.js');
let _tags = null;
@@ -66,7 +65,7 @@ function _refreshStylesheet() {
document.head.appendChild(_stylesheet);
for (let category of getAllCategories()) {
_stylesheet.sheet.insertRule(
- '.tag-{0} { color: {1} }'.format(category.name, category.color),
+ `.tag-${category.name} { color: ${category.color} }`,
_stylesheet.sheet.cssRules.length);
}
}
diff --git a/client/js/util/misc.js b/client/js/util/misc.js
index af333642..423fe393 100644
--- a/client/js/util/misc.js
+++ b/client/js/util/misc.js
@@ -57,7 +57,7 @@ function formatSearchQuery(dict) {
for (let key of Object.keys(dict)) {
const value = dict[key];
if (value) {
- result.push('{0}={1}'.format(key, value));
+ result.push(`${key}=${value}`);
}
}
return result.join(';');
@@ -79,10 +79,34 @@ function parseSearchQueryRoute(ctx, next) {
next();
}
+function unindent(callSite, ...args) {
+ function format(str) {
+ let size = -1;
+ return str.replace(/\n(\s+)/g, (m, m1) => {
+ if (size < 0) {
+ size = m1.replace(/\t/g, ' ').length;
+ }
+ return "\n" + m1.slice(Math.min(m1.length, size));
+ });
+ }
+ if (typeof callSite === 'string') {
+ return format(callSite);
+ }
+ if (typeof callSite === 'function') {
+ return (...args) => format(callSite(...args));
+ }
+ let output = callSite
+ .slice(0, args.length + 1)
+ .map((text, i) => (i === 0 ? '' : args[i - 1]) + text)
+ .join('');
+ return format(output);
+}
+
module.exports = {
range: range,
formatSearchQuery: formatSearchQuery,
parseSearchQuery: parseSearchQuery,
parseSearchQueryRoute: parseSearchQueryRoute,
formatRelativeTime: formatRelativeTime,
+ unindent: unindent,
};
diff --git a/client/js/util/polyfill.js b/client/js/util/polyfill.js
index f11d13cd..606d29d7 100644
--- a/client/js/util/polyfill.js
+++ b/client/js/util/polyfill.js
@@ -22,25 +22,6 @@ Promise.prototype.always = function(onResolveOrReject) {
});
};
-// non standard
-if (!String.prototype.format) {
- String.prototype.format = function() {
- let str = this.toString();
- if (!arguments.length) {
- return str;
- }
- const type = typeof arguments[0];
- const args = (type == 'string' || type == 'number') ?
- arguments : arguments[0];
- for (let arg in args) {
- str = str.replace(
- new RegExp('\\{' + arg + '\\}', 'gi'),
- () => { return args[arg]; });
- }
- return str;
- };
-}
-
// non standard
Number.prototype.between = function(a, b, inclusive) {
const min = Math.min(a, b);
diff --git a/client/js/util/views.js b/client/js/util/views.js
index 2e032edc..d432ee1f 100644
--- a/client/js/util/views.js
+++ b/client/js/util/views.js
@@ -36,7 +36,7 @@ function makeThumbnail(url) {
'span',
{
class: 'thumbnail',
- style: 'background-image: url(\'{0}\')'.format(url)
+ style: `background-image: url(\'${url}\')`,
},
makeVoidElement('img', {alt: 'thumbnail', src: url}));
}
@@ -164,18 +164,17 @@ function _serializeElement(name, attributes) {
attributes[key] === undefined) {
return '';
}
- return '{0}="{1}"'.format(key, attributes[key]);
+ return `${key}="${attributes[key]}"`;
}))
.join(' ');
}
function makeNonVoidElement(name, attributes, content) {
- return '<{0}>{1}{2}>'.format(
- _serializeElement(name, attributes), content, name);
+ return `<${_serializeElement(name, attributes)}>${content}${name}>`;
}
function makeVoidElement(name, attributes) {
- return '<{0}/>'.format(_serializeElement(name, attributes));
+ return `<${_serializeElement(name, attributes)}/>`;
}
function _messageHandler(target, message, className) {
diff --git a/client/js/views/endless_page_view.js b/client/js/views/endless_page_view.js
index c4e36463..6c54d3b0 100644
--- a/client/js/views/endless_page_view.js
+++ b/client/js/views/endless_page_view.js
@@ -4,6 +4,10 @@ const page = require('page');
const events = require('../events.js');
const views = require('../util/views.js');
+function _formatUrl(url, page) {
+ return url.replace('{page}', page);
+}
+
class EndlessPageView {
constructor() {
this._holderTemplate = views.getTemplate('endless-pager');
@@ -51,7 +55,7 @@ class EndlessPageView {
let topPageNumber = parseInt(topPageNode.getAttribute('data-page'));
if (topPageNumber !== this.currentPage) {
page.replace(
- ctx.clientUrl.format({page: topPageNumber}),
+ _formatUrl(ctx.clientUrl, topPageNumber),
null,
false,
false);
diff --git a/client/js/views/manual_page_view.js b/client/js/views/manual_page_view.js
index 9e176f8f..baeafc21 100644
--- a/client/js/views/manual_page_view.js
+++ b/client/js/views/manual_page_view.js
@@ -6,6 +6,10 @@ const keyboard = require('../util/keyboard.js');
const misc = require('../util/misc.js');
const views = require('../util/views.js');
+function _formatUrl(url, page) {
+ return url.replace('{page}', page);
+}
+
function _removeConsecutiveDuplicates(a) {
return a.filter((item, pos, ary) => {
return !pos || item != ary[pos - 1];
@@ -43,7 +47,7 @@ function _getPages(currentPage, pageNumbers, clientUrl) {
}
pages.push({
number: page,
- link: clientUrl.format({page: page}),
+ link: _formatUrl(clientUrl, page),
active: currentPage === page,
});
lastPage = page;
@@ -80,19 +84,19 @@ class ManualPageView {
keyboard.bind(['a', 'left'], () => {
if (currentPage > 1) {
- page.show(ctx.clientUrl.format({page: currentPage - 1}));
+ page.show(_formatUrl(ctx.clientUrl, currentPage - 1));
}
});
keyboard.bind(['d', 'right'], () => {
if (currentPage < totalPages) {
- page.show(ctx.clientUrl.format({page: currentPage + 1}));
+ page.show(_formatUrl(ctx.clientUrl, currentPage + 1));
}
});
if (response.total) {
views.showView(pageNav, this._navTemplate({
- prevLink: ctx.clientUrl.format({page: currentPage - 1}),
- nextLink: ctx.clientUrl.format({page: currentPage + 1}),
+ prevLink: _formatUrl(ctx.clientUrl, currentPage - 1),
+ nextLink: _formatUrl(ctx.clientUrl, currentPage + 1),
prevLinkActive: currentPage > 1,
nextLinkActive: currentPage < totalPages,
pages: pages,