diff --git a/.eslintrc.json b/.eslintrc.json
index d0b9e04b87..f74366a20c 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -85,6 +85,7 @@
}
],
"no-use-before-define": ["error", {"functions": false}],
+ "no-useless-concat": "error",
"no-useless-constructor": "error",
"no-var": "error",
"object-shorthand": "error",
diff --git a/frontend_tests/node_tests/compose.js b/frontend_tests/node_tests/compose.js
index f310cbb2a4..1686389188 100644
--- a/frontend_tests/node_tests/compose.js
+++ b/frontend_tests/node_tests/compose.js
@@ -690,7 +690,7 @@ run_test("send_message", () => {
// Setting message content with a host server link and we will assert
// later that this has been converted to a relative link.
- $("#compose-textarea").val("[foobar]" + "(https://foo.com/user_uploads/123456)");
+ $("#compose-textarea").val("[foobar](https://foo.com/user_uploads/123456)");
$("#compose-textarea").trigger("blur");
$("#compose-send-status").show();
$("#compose-send-button").prop("disabled", true);
diff --git a/frontend_tests/node_tests/list_render.js b/frontend_tests/node_tests/list_render.js
index 2f4380497d..384150030f 100644
--- a/frontend_tests/node_tests/list_render.js
+++ b/frontend_tests/node_tests/list_render.js
@@ -223,7 +223,7 @@ run_test("filtering", () => {
const new_data = ["greta", "faye", "gary", "frank", "giraffe", "fox"];
widget.replace_list_data(new_data);
- expected_html = "
greta
" + "gary
" + "giraffe
";
+ expected_html = "greta
gary
giraffe
";
assert.deepEqual(container.appended_data.html(), expected_html);
});
@@ -240,7 +240,7 @@ run_test("no filtering", () => {
const widget = list_render.create(container, ["apple", "banana"], opts);
widget.render();
- const expected_html = "apple
" + "banana
";
+ const expected_html = "apple
banana
";
assert.deepEqual(container.appended_data.html(), expected_html);
});
diff --git a/frontend_tests/node_tests/markdown.js b/frontend_tests/node_tests/markdown.js
index c815311b3c..fce285420e 100644
--- a/frontend_tests/node_tests/markdown.js
+++ b/frontend_tests/node_tests/markdown.js
@@ -364,12 +364,12 @@ run_test("marked", () => {
{
input: "This is a #**Denmark>some topic** stream_topic link",
expected:
- 'This is a #Denmark > some topic stream_topic link
',
+ 'This is a #Denmark > some topic stream_topic link
',
},
{
input: "This has two links: #**Denmark>some topic** and #**social>other topic**.",
expected:
- 'This has two links: #Denmark > some topic and #social > other topic.
',
+ 'This has two links: #Denmark > some topic and #social > other topic.
',
},
{
input: "This is not a #**Denmark>** stream_topic link",
@@ -512,7 +512,7 @@ run_test("marked", () => {
{
input: "#**Bobby Tables
**",
expected:
- '#Bobby <h1 > Tables</h1>
',
+ '#Bobby <h1 > Tables</h1>
',
},
{
input: "#**& & &**",
@@ -522,7 +522,7 @@ run_test("marked", () => {
{
input: "#**& & &>& & &**",
expected:
- '#& & & > & & &
',
+ '#& & & > & & &
',
},
];
diff --git a/frontend_tests/node_tests/people.js b/frontend_tests/node_tests/people.js
index ad895263d0..5793bf006c 100644
--- a/frontend_tests/node_tests/people.js
+++ b/frontend_tests/node_tests/people.js
@@ -885,7 +885,7 @@ run_test("updates", () => {
// old email.
blueslip.expect(
"warn",
- "Obsolete email passed to get_by_email: " + "FOO@example.com new email = bar@example.com",
+ "Obsolete email passed to get_by_email: FOO@example.com new email = bar@example.com",
);
person = people.get_by_email(old_email);
assert.equal(person.user_id, user_id);
diff --git a/frontend_tests/node_tests/vdom.js b/frontend_tests/node_tests/vdom.js
index f64899d9b6..0ca5b50494 100644
--- a/frontend_tests/node_tests/vdom.js
+++ b/frontend_tests/node_tests/vdom.js
@@ -15,10 +15,7 @@ run_test("basics", () => {
const html = vdom.render_tag(ul);
- assert.equal(
- html,
- '",
- );
+ assert.equal(html, '');
});
run_test("attribute escaping", () => {
@@ -59,7 +56,7 @@ run_test("attribute updates", () => {
const html = vdom.render_tag(ul);
- assert.equal(html, '");
+ assert.equal(html, '');
let updated;
let removed;
@@ -135,10 +132,7 @@ run_test("children", () => {
vdom.update(replace_content, find, ul);
- assert.equal(
- rendered_html,
- "\n" + "- foo1
\n" + "- foo2
\n" + "- foo3
\n" + "
",
- );
+ assert.equal(rendered_html, "");
// Force a complete redraw.
const new_nodes = make_children([4, 5]);
@@ -150,10 +144,7 @@ run_test("children", () => {
const new_ul = vdom.ul(new_opts);
vdom.update(replace_content, find, new_ul, ul);
- assert.equal(
- rendered_html,
- '\n' + "- foo4
\n" + "- foo5
\n" + "
",
- );
+ assert.equal(rendered_html, '');
});
run_test("partial updates", () => {
@@ -176,10 +167,7 @@ run_test("partial updates", () => {
vdom.update(replace_content, find, ul);
- assert.equal(
- rendered_html,
- "\n" + "- foo1
\n" + "- foo2
\n" + "- foo3
\n" + "
",
- );
+ assert.equal(rendered_html, "");
replace_content = () => {
throw new Error("should not replace entire html");
diff --git a/static/js/alert_words.js b/static/js/alert_words.js
index 96e4a3e64d..ce2941af7a 100644
--- a/static/js/alert_words.js
+++ b/static/js/alert_words.js
@@ -37,10 +37,7 @@ exports.process_message = function (message) {
const before_punctuation = "\\s|^|>|[\\(\\\".,';\\[]";
const after_punctuation = "\\s|$|<|[\\)\\\"\\?!:.,';\\]!]";
- const regex = new RegExp(
- "(" + before_punctuation + ")" + "(" + clean + ")" + "(" + after_punctuation + ")",
- "ig",
- );
+ const regex = new RegExp(`(${before_punctuation})(${clean})(${after_punctuation})`, "ig");
message.content = message.content.replace(
regex,
(match, before, word, after, offset, content) => {
diff --git a/static/js/blueslip.js b/static/js/blueslip.js
index c60c98365e..62d8189ea2 100644
--- a/static/js/blueslip.js
+++ b/static/js/blueslip.js
@@ -155,7 +155,7 @@ function report_error(msg, stack, opts) {
error() {
if (opts.show_ui_msg && ui_report !== undefined) {
ui_report.message(
- "Oops. It seems something has gone wrong. " + "Please try reloading the page.",
+ "Oops. It seems something has gone wrong. Please try reloading the page.",
$("#home-error"),
"alert-error",
);
diff --git a/static/js/hash_util.js b/static/js/hash_util.js
index ed84eac58c..7db2bc8594 100644
--- a/static/js/hash_util.js
+++ b/static/js/hash_util.js
@@ -166,7 +166,7 @@ exports.by_conversation_and_time_uri = function (message) {
};
exports.stream_edit_uri = function (sub) {
- const hash = "#streams" + "/" + sub.stream_id + "/" + exports.encodeHashComponent(sub.name);
+ const hash = `#streams/${sub.stream_id}/${exports.encodeHashComponent(sub.name)}`;
return hash;
};
diff --git a/static/js/markdown.js b/static/js/markdown.js
index ea0bcdef8c..d84d52cae6 100644
--- a/static/js/markdown.js
+++ b/static/js/markdown.js
@@ -102,7 +102,7 @@ exports.apply_markdown = function (message) {
userMentionHandler(mention, silently) {
if (mention === "all" || mention === "everyone" || mention === "stream") {
message.mentioned = true;
- return '' + "@" + mention + "";
+ return `@${_.escape(mention)}`;
}
let full_name;
@@ -160,15 +160,15 @@ exports.apply_markdown = function (message) {
}
let str = "";
if (silently) {
- str += '';
+ str += ``;
} else {
- str += '@';
+ str += `@`;
}
// If I mention "@aLiCe sMITH", I still want "Alice Smith" to
// show in the pill.
const actual_full_name = helpers.get_actual_name_from_user_id(user_id);
- return str + _.escape(actual_full_name) + "";
+ return `${str}${_.escape(actual_full_name)}`;
},
groupMentionHandler(name) {
const group = helpers.get_user_group_from_name(name);
@@ -176,14 +176,9 @@ exports.apply_markdown = function (message) {
if (helpers.is_member_of_user_group(group.id, helpers.my_user_id())) {
message.mentioned = true;
}
- return (
- '' +
- "@" +
- _.escape(group.name) +
- ""
- );
+ return `@${_.escape(group.name)}`;
}
return undefined;
},
@@ -251,19 +246,9 @@ exports.is_status_message = function (raw_content) {
};
function make_emoji_span(codepoint, title, alt_text) {
- return (
- '' +
- alt_text +
- ""
- );
+ return `${_.escape(alt_text)}`;
}
function handleUnicodeEmoji(unicode_emoji) {
@@ -293,17 +278,9 @@ function handleEmoji(emoji_name) {
const emoji_url = emoji.get_realm_emoji_url(emoji_name);
if (emoji_url) {
- return (
- ''
- );
+ return ``;
}
const codepoint = emoji.get_emoji_codepoint(emoji_name);
@@ -350,18 +327,9 @@ function handleStream(stream_name) {
return undefined;
}
const href = helpers.stream_hash(stream.stream_id);
- return (
- '" +
- "#" +
- _.escape(stream.name) +
- ""
- );
+ return `#${_.escape(stream.name)}`;
}
function handleStreamTopic(stream_name, topic) {
@@ -370,18 +338,10 @@ function handleStreamTopic(stream_name, topic) {
return undefined;
}
const href = helpers.stream_topic_hash(stream.stream_id, topic);
- const text = "#" + _.escape(stream.name) + " > " + _.escape(topic);
- return (
- '" +
- text +
- ""
- );
+ const text = `#${stream.name} > ${topic}`;
+ return `${_.escape(text)}`;
}
function handleRealmFilter(pattern, matches) {
@@ -404,7 +364,7 @@ function handleTex(tex, fullmatch) {
} catch (error) {
if (error.message.startsWith("KaTeX parse error")) {
// TeX syntax error
- return '' + _.escape(fullmatch) + "";
+ return `${_.escape(fullmatch)}`;
}
blueslip.error(error);
return undefined;
diff --git a/static/js/portico/integrations_dev_panel.js b/static/js/portico/integrations_dev_panel.js
index 87a0e4cab6..fc0a078bb4 100644
--- a/static/js/portico/integrations_dev_panel.js
+++ b/static/js/portico/integrations_dev_panel.js
@@ -188,7 +188,7 @@ function handle_unsuccessful_response(response) {
try {
const status_code = response.statusCode().status;
response = JSON.parse(response.responseText);
- set_results_notice("Result: " + "(" + status_code + ") " + response.msg, "warning");
+ set_results_notice(`Result: (${status_code}) ${response.msg}`, "warning");
} catch {
// If the response is not a JSON response, then it is probably
// Django returning an HTML response containing a stack trace
diff --git a/static/js/sent_messages.js b/static/js/sent_messages.js
index c2e9702a2b..de81dea53a 100644
--- a/static/js/sent_messages.js
+++ b/static/js/sent_messages.js
@@ -73,7 +73,7 @@ class MessageState {
}
blueslip.log(
- "Restarting get_events due to " + "delayed receipt of sent message " + this.local_id,
+ `Restarting get_events due to delayed receipt of sent message ${this.local_id}`,
);
server_events.restart_get_events();
diff --git a/static/js/settings_streams.js b/static/js/settings_streams.js
index 233b181294..a06e77f4af 100644
--- a/static/js/settings_streams.js
+++ b/static/js/settings_streams.js
@@ -81,7 +81,7 @@ function make_stream_default(stream_id) {
exports.delete_default_stream = function (stream_id, default_stream_row, alert_element) {
channel.del({
- url: "/json/default_streams" + "?" + $.param({stream_id}),
+ url: "/json/default_streams?" + $.param({stream_id}),
error(xhr) {
ui_report.generic_row_button_error(xhr, alert_element);
},