diff --git a/.eslintrc.json b/.eslintrc.json index accbe31e72..e29c6e5a6f 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -109,7 +109,6 @@ "UserSearch": false, "WinChan": false, "XDate": false, - "_": false, "activity": false, "admin": false, "alert_words": false, diff --git a/frontend_tests/node_tests/buddy_data.js b/frontend_tests/node_tests/buddy_data.js index 7f6a08ef89..01b761ec8c 100644 --- a/frontend_tests/node_tests/buddy_data.js +++ b/frontend_tests/node_tests/buddy_data.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + const _page_params = {}; set_global("page_params", _page_params); diff --git a/frontend_tests/node_tests/buddy_list.js b/frontend_tests/node_tests/buddy_list.js index 4aaff353ec..c394c986b2 100644 --- a/frontend_tests/node_tests/buddy_list.js +++ b/frontend_tests/node_tests/buddy_list.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + set_global("$", global.make_zjquery()); zrequire("people"); zrequire("buddy_data"); diff --git a/frontend_tests/node_tests/channel.js b/frontend_tests/node_tests/channel.js index b7435c0712..b8bb5ef39d 100644 --- a/frontend_tests/node_tests/channel.js +++ b/frontend_tests/node_tests/channel.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + set_global("$", {}); set_global("reload", {}); diff --git a/frontend_tests/node_tests/components.js b/frontend_tests/node_tests/components.js index 164c07ef2c..18b82a5799 100644 --- a/frontend_tests/node_tests/components.js +++ b/frontend_tests/node_tests/components.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + zrequire("keydown_util"); zrequire("components"); diff --git a/frontend_tests/node_tests/emoji_picker.js b/frontend_tests/node_tests/emoji_picker.js index 6e7ddadd5a..7b7e4c8600 100644 --- a/frontend_tests/node_tests/emoji_picker.js +++ b/frontend_tests/node_tests/emoji_picker.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + const emoji = zrequire("emoji", "shared/js/emoji"); zrequire("emoji_picker"); diff --git a/frontend_tests/node_tests/message_fetch.js b/frontend_tests/node_tests/message_fetch.js index c334dc84cf..13bb9081bf 100644 --- a/frontend_tests/node_tests/message_fetch.js +++ b/frontend_tests/node_tests/message_fetch.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + set_global("$", global.make_zjquery()); set_global("document", "document-stub"); diff --git a/frontend_tests/node_tests/message_list_view.js b/frontend_tests/node_tests/message_list_view.js index 858f6fc09d..0c4bb320b2 100644 --- a/frontend_tests/node_tests/message_list_view.js +++ b/frontend_tests/node_tests/message_list_view.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + set_global("$", global.make_zjquery()); set_global("document", "document-stub"); diff --git a/frontend_tests/node_tests/people.js b/frontend_tests/node_tests/people.js index 2a1bcdddbb..9c022d72b0 100644 --- a/frontend_tests/node_tests/people.js +++ b/frontend_tests/node_tests/people.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + zrequire("people"); set_global("message_store", {}); set_global("page_params", {}); diff --git a/frontend_tests/node_tests/settings_user_groups.js b/frontend_tests/node_tests/settings_user_groups.js index 55ededb465..4f9953c336 100644 --- a/frontend_tests/node_tests/settings_user_groups.js +++ b/frontend_tests/node_tests/settings_user_groups.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + zrequire("user_pill"); zrequire("settings_user_groups"); diff --git a/frontend_tests/node_tests/stream_data.js b/frontend_tests/node_tests/stream_data.js index 214952fb8a..f35f227937 100644 --- a/frontend_tests/node_tests/stream_data.js +++ b/frontend_tests/node_tests/stream_data.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + set_global("page_params", { is_admin: false, realm_users: [], diff --git a/frontend_tests/node_tests/topic_list_data.js b/frontend_tests/node_tests/topic_list_data.js index ce65b33f04..3595654e4f 100644 --- a/frontend_tests/node_tests/topic_list_data.js +++ b/frontend_tests/node_tests/topic_list_data.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + set_global("narrow_state", {}); set_global("unread", {}); set_global("muting", {}); diff --git a/frontend_tests/node_tests/unread.js b/frontend_tests/node_tests/unread.js index 301a3eb765..41648abdb1 100644 --- a/frontend_tests/node_tests/unread.js +++ b/frontend_tests/node_tests/unread.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + zrequire("muting"); zrequire("people"); zrequire("stream_data"); diff --git a/frontend_tests/node_tests/util.js b/frontend_tests/node_tests/util.js index 1c85ea7bea..50e4778720 100644 --- a/frontend_tests/node_tests/util.js +++ b/frontend_tests/node_tests/util.js @@ -1,4 +1,5 @@ const {JSDOM} = require("jsdom"); +const _ = require("lodash"); set_global("$", global.make_zjquery()); set_global("DOMParser", new JSDOM().window.DOMParser); diff --git a/frontend_tests/zjsunit/finder.js b/frontend_tests/zjsunit/finder.js index 3aced6e9e5..e5adbacfb4 100644 --- a/frontend_tests/zjsunit/finder.js +++ b/frontend_tests/zjsunit/finder.js @@ -1,7 +1,7 @@ const fs = require("fs"); const path = require("path"); -const _ = require("underscore/underscore.js"); +const _ = require("lodash"); exports.find_files_to_run = function () { let oneFileFilter = []; diff --git a/frontend_tests/zjsunit/index.js b/frontend_tests/zjsunit/index.js index c932a165f8..1aa5193ab8 100644 --- a/frontend_tests/zjsunit/index.js +++ b/frontend_tests/zjsunit/index.js @@ -2,7 +2,7 @@ const fs = require("fs"); const Module = require("module"); const path = require("path"); -const escapeRegExp = require("lodash/escapeRegExp"); +const _ = require("lodash"); const finder = require("./finder.js"); const handlebars = require("./handlebars.js"); @@ -15,18 +15,15 @@ const zjquery = require("./zjquery.js"); require("@babel/register")({ extensions: [".es6", ".es", ".jsx", ".js", ".mjs", ".ts"], only: [ - new RegExp("^" + escapeRegExp(path.resolve(__dirname, "../../static/js")) + path.sep), + new RegExp("^" + _.escapeRegExp(path.resolve(__dirname, "../../static/js")) + path.sep), new RegExp( - "^" + escapeRegExp(path.resolve(__dirname, "../../static/shared/js")) + path.sep, + "^" + _.escapeRegExp(path.resolve(__dirname, "../../static/shared/js")) + path.sep, ), ], plugins: ["rewire-ts"], }); global.assert = require("assert").strict; -global._ = require("underscore/underscore.js"); - -const _ = global._; // Create a helper function to avoid sneaky delays in tests. function immediate(f) { diff --git a/frontend_tests/zjsunit/markdown_assert.js b/frontend_tests/zjsunit/markdown_assert.js index fff9fa5dbd..73778525fb 100644 --- a/frontend_tests/zjsunit/markdown_assert.js +++ b/frontend_tests/zjsunit/markdown_assert.js @@ -21,7 +21,7 @@ */ const {JSDOM} = require("jsdom"); -const _ = require("underscore"); +const _ = require("lodash"); const mdiff = require("./mdiff.js"); diff --git a/frontend_tests/zjsunit/namespace.js b/frontend_tests/zjsunit/namespace.js index 10d8b2bd40..be767e1048 100644 --- a/frontend_tests/zjsunit/namespace.js +++ b/frontend_tests/zjsunit/namespace.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + const requires = []; const new_globals = new Set(); let old_globals = {}; diff --git a/package.json b/package.json index 12022d6a06..b7724154bf 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "jquery-validation": "^1.19.0", "js-yaml": "^3.13.1", "katex": "^0.12.0", + "lodash": "^4.17.19", "mini-css-extract-plugin": "^0.9.0", "moment": "^2.24.0", "moment-timezone": "^0.5.25", @@ -67,7 +68,6 @@ "style-loader": "^1.0.0", "terser-webpack-plugin": "^3.0.3", "turndown": "^6.0.0", - "underscore": "^1.9.1", "unorm": "^1.6.0", "webfonts-loader": "^5.0.0", "webpack": "^4.33.0", @@ -84,7 +84,6 @@ "@types/node": "^14.0.11", "@types/optimize-css-assets-webpack-plugin": "^5.0.1", "@types/terser-webpack-plugin": "^3.0.0", - "@types/underscore": "^1.8.18", "@types/webpack": "^4.4.32", "@types/webpack-dev-server": "^3.1.6", "@typescript-eslint/eslint-plugin": "^3.1.0", diff --git a/static/js/activity.js b/static/js/activity.js index e96eb2e204..77c011c013 100644 --- a/static/js/activity.js +++ b/static/js/activity.js @@ -1,3 +1,4 @@ +const _ = require("lodash"); /* Helpers for detecting user activity and managing user idle states */ diff --git a/static/js/archive.js b/static/js/archive.js index badfa4a836..bd6dd997b8 100644 --- a/static/js/archive.js +++ b/static/js/archive.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + const render_archive_message_group = require("../templates/archive_message_group.hbs"); function should_separate_into_groups(current_msg_time, next_msg_time) { diff --git a/static/js/bot_data.js b/static/js/bot_data.js index 98263ff9da..3244ac91d8 100644 --- a/static/js/bot_data.js +++ b/static/js/bot_data.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + const bots = new Map(); const bot_fields = [ diff --git a/static/js/bundles/common.js b/static/js/bundles/common.js index 9c0159223f..a5eed263e1 100644 --- a/static/js/bundles/common.js +++ b/static/js/bundles/common.js @@ -2,7 +2,6 @@ import "core-js/features/promise"; import "core-js/features/symbol"; import "../../../tools/debug-require"; import "jquery/dist/jquery.js"; -import "underscore/underscore.js"; import "../page_params.js"; import "../csrf.js"; import "../blueslip.js"; diff --git a/static/js/click_handlers.js b/static/js/click_handlers.js index c9db3b2d60..76a0bfa806 100644 --- a/static/js/click_handlers.js +++ b/static/js/click_handlers.js @@ -1,3 +1,4 @@ +const _ = require("lodash"); // You won't find every click handler here, but it's a good place to start! const render_buddy_list_tooltip = require("../templates/buddy_list_tooltip.hbs"); diff --git a/static/js/color_data.js b/static/js/color_data.js index 80a04753f8..6a9da6d296 100644 --- a/static/js/color_data.js +++ b/static/js/color_data.js @@ -1,3 +1,4 @@ +const _ = require("lodash"); // These colors are used now for streams. const stream_colors = [ "#76ce90", diff --git a/static/js/compose_fade.js b/static/js/compose_fade.js index 8e9e1a916d..bf1aef1850 100644 --- a/static/js/compose_fade.js +++ b/static/js/compose_fade.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + const util = require("./util"); let focused_recipient; diff --git a/static/js/filter.js b/static/js/filter.js index b1ef2e9ca1..e5461f15b0 100644 --- a/static/js/filter.js +++ b/static/js/filter.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + const util = require("./util"); function zephyr_stream_name_match(message, operand) { diff --git a/static/js/hotspots.js b/static/js/hotspots.js index 38466fd000..aa15ee6eff 100644 --- a/static/js/hotspots.js +++ b/static/js/hotspots.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + const render_hotspot_overlay = require("../templates/hotspot_overlay.hbs"); const render_intro_reply_hotspot = require("../templates/intro_reply_hotspot.hbs"); diff --git a/static/js/huddle_data.js b/static/js/huddle_data.js index e3a07f30f6..a4ee46cac7 100644 --- a/static/js/huddle_data.js +++ b/static/js/huddle_data.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + const huddle_timestamps = new Map(); exports.process_loaded_messages = function (messages) { diff --git a/static/js/markdown.js b/static/js/markdown.js index ab697ccdb0..344cd5f58b 100644 --- a/static/js/markdown.js +++ b/static/js/markdown.js @@ -1,4 +1,5 @@ const katex = require("katex/dist/katex.min.js"); +const _ = require("lodash"); const fenced_code = require("../shared/js/fenced_code"); diff --git a/static/js/message_flags.js b/static/js/message_flags.js index 23e8380804..f3530fd4e6 100644 --- a/static/js/message_flags.js +++ b/static/js/message_flags.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + function send_flag_update(message, flag, op) { channel.post({ url: "/json/messages/flags", diff --git a/static/js/message_list_data.js b/static/js/message_list_data.js index 45439fa36b..80d9d8ce04 100644 --- a/static/js/message_list_data.js +++ b/static/js/message_list_data.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + const util = require("./util"); function MessageListData(opts) { diff --git a/static/js/message_list_view.js b/static/js/message_list_view.js index af83e9c586..51117509b0 100644 --- a/static/js/message_list_view.js +++ b/static/js/message_list_view.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + const render_bookend = require("../templates/bookend.hbs"); const render_message_group = require("../templates/message_group.hbs"); const render_recipient_row = require("../templates/recipient_row.hbs"); @@ -475,7 +477,7 @@ MessageListView.prototype = { // rerender the last message message_actions.rerender_messages_next_same_sender.push(prev_msg_container); message_actions.append_messages = _.first(new_message_groups).message_containers; - new_message_groups = _.rest(new_message_groups); + new_message_groups = _.tail(new_message_groups); } else if (first_group !== undefined && second_group !== undefined) { if (same_day(prev_msg_container, curr_msg_container)) { clear_group_date_divider(second_group); diff --git a/static/js/message_scroll.js b/static/js/message_scroll.js index d011b714e5..e929c7d565 100644 --- a/static/js/message_scroll.js +++ b/static/js/message_scroll.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + let actively_scrolling = false; // Tracks whether the next scroll that will complete is initiated by diff --git a/static/js/notifications.js b/static/js/notifications.js index 3625158a2a..7664c8330e 100644 --- a/static/js/notifications.js +++ b/static/js/notifications.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + const render_compose_notification = require("../templates/compose_notification.hbs"); const render_notification = require("../templates/notification.hbs"); diff --git a/static/js/people.js b/static/js/people.js index f69bf72c0a..4b1fbda9d4 100644 --- a/static/js/people.js +++ b/static/js/people.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + require("unorm"); // String.prototype.normalize polyfill for IE11 const typeahead = require("../shared/js/typeahead"); diff --git a/static/js/pm_list_dom.js b/static/js/pm_list_dom.js index ca3d5184f5..95250b7005 100644 --- a/static/js/pm_list_dom.js +++ b/static/js/pm_list_dom.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + const render_pm_list_item = require("../templates/pm_list_item.hbs"); exports.keyed_pm_li = (convo) => { diff --git a/static/js/portico/integrations.js b/static/js/portico/integrations.js index 4e80cb89b1..c2367ca155 100644 --- a/static/js/portico/integrations.js +++ b/static/js/portico/integrations.js @@ -1,3 +1,5 @@ +import _ from "lodash"; + import blueslip from "./../blueslip"; import * as google_analytics from "./google-analytics.js"; import {path_parts} from "./landing-page"; diff --git a/static/js/portico/team.js b/static/js/portico/team.js index 11596477cf..0d1c994f65 100644 --- a/static/js/portico/team.js +++ b/static/js/portico/team.js @@ -1,3 +1,5 @@ +import _ from "lodash"; + const contributors_list = page_params.contributors; const repo_name_to_tab_name = { diff --git a/static/js/reactions.js b/static/js/reactions.js index 33edd7c9bc..bb49c3e961 100644 --- a/static/js/reactions.js +++ b/static/js/reactions.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + const emoji = require("../shared/js/emoji"); const render_message_reaction = require("../templates/message_reaction.hbs"); diff --git a/static/js/server_events.js b/static/js/server_events.js index 1ca9e04fb2..8b4a689b12 100644 --- a/static/js/server_events.js +++ b/static/js/server_events.js @@ -1,3 +1,4 @@ +const _ = require("lodash"); // Docs: https://zulip.readthedocs.io/en/latest/subsystems/events-system.html let waiting_on_homeview_load = true; diff --git a/static/js/settings_account.js b/static/js/settings_account.js index 82a08e6e67..f963c2ed57 100644 --- a/static/js/settings_account.js +++ b/static/js/settings_account.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + const render_settings_api_key_modal = require("../templates/settings/api_key_modal.hbs"); const render_settings_custom_user_profile_field = require("../templates/settings/custom_user_profile_field.hbs"); const render_settings_dev_env_email_access = require("../templates/settings/dev_env_email_access.hbs"); diff --git a/static/js/settings_user_groups.js b/static/js/settings_user_groups.js index 1c3072a537..3ab185bd00 100644 --- a/static/js/settings_user_groups.js +++ b/static/js/settings_user_groups.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + const render_admin_user_group_list = require("../templates/admin_user_group_list.hbs"); const render_confirm_delete_user = require("../templates/confirm_delete_user.hbs"); diff --git a/static/js/stream_color.js b/static/js/stream_color.js index b8191eef9e..db9a0b6a58 100644 --- a/static/js/stream_color.js +++ b/static/js/stream_color.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + exports.default_color = "#c2c2c2"; // Classes which could be returned by get_color_class. diff --git a/static/js/stream_list.js b/static/js/stream_list.js index 99e1e72eed..b9daba6a9f 100644 --- a/static/js/stream_list.js +++ b/static/js/stream_list.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + const render_stream_privacy = require("../templates/stream_privacy.hbs"); const render_stream_sidebar_row = require("../templates/stream_sidebar_row.hbs"); diff --git a/static/js/subs.js b/static/js/subs.js index 86325d6d5c..f923724978 100644 --- a/static/js/subs.js +++ b/static/js/subs.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + const render_subscription = require("../templates/subscription.hbs"); const render_subscription_settings = require("../templates/subscription_settings.hbs"); const render_subscription_table_body = require("../templates/subscription_table_body.hbs"); diff --git a/static/js/topic_list.js b/static/js/topic_list.js index 3cd87ba3e7..ee7b960168 100644 --- a/static/js/topic_list.js +++ b/static/js/topic_list.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + const render_more_topics = require("../templates/more_topics.hbs"); const render_more_topics_spinner = require("../templates/more_topics_spinner.hbs"); const render_topic_list_item = require("../templates/topic_list_item.hbs"); diff --git a/static/js/typing_data.js b/static/js/typing_data.js index 51ce3bed74..2a2017e5bc 100644 --- a/static/js/typing_data.js +++ b/static/js/typing_data.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + const util = require("./util"); // See docs/subsystems/typing-indicators.md for details on typing indicators. @@ -46,7 +48,7 @@ exports.get_group_typists = function (group) { exports.get_all_typists = function () { let typists = [].concat(...Array.from(typist_dct.values())); typists = util.sorted_ids(typists); - typists = _.uniq(typists, true); + typists = _.sortedUniq(typists); return typists; }; diff --git a/static/js/ui_init.js b/static/js/ui_init.js index f8cfa2170c..a21f658c49 100644 --- a/static/js/ui_init.js +++ b/static/js/ui_init.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + const generated_emoji_codes = require("../generated/emoji/emoji_codes.json"); const emoji = require("../shared/js/emoji"); diff --git a/static/js/ui_report.js b/static/js/ui_report.js index 19ec1d5ae5..c23491251c 100644 --- a/static/js/ui_report.js +++ b/static/js/ui_report.js @@ -1,3 +1,4 @@ +const _ = require("lodash"); /* Arguments used in the report_* functions are, response- response that we want to display status_box- element being used to display the response diff --git a/static/js/util.js b/static/js/util.js index 5a4a8bea24..f8798ff84d 100644 --- a/static/js/util.js +++ b/static/js/util.js @@ -1,3 +1,4 @@ +const _ = require("lodash"); // From MDN: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Math/random exports.random_int = function random_int(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; @@ -229,7 +230,7 @@ exports.sorted_ids = function (ids) { // it also makes sure we don't mutate the list. let id_list = ids.map(to_int); id_list.sort((a, b) => a - b); - id_list = _.uniq(id_list, true); + id_list = _.sortedUniq(id_list); return id_list; }; diff --git a/static/js/vdom.js b/static/js/vdom.js index edf523dd0b..8b46c83a66 100644 --- a/static/js/vdom.js +++ b/static/js/vdom.js @@ -1,3 +1,5 @@ +const _ = require("lodash"); + exports.eq_array = (a, b, eq) => { if (a === b) { // either both are undefined, or they diff --git a/static/shared/js/fenced_code.js b/static/shared/js/fenced_code.js index 752801b43a..b0594483d2 100644 --- a/static/shared/js/fenced_code.js +++ b/static/shared/js/fenced_code.js @@ -1,5 +1,5 @@ import katex from "katex/dist/katex.min.js"; -import _ from "underscore"; +import _ from "lodash"; // Parsing routine that can be dropped in to message parsing // and formats code blocks diff --git a/static/shared/js/typing_status.js b/static/shared/js/typing_status.js index de2db772bb..783d84b71b 100644 --- a/static/shared/js/typing_status.js +++ b/static/shared/js/typing_status.js @@ -1,4 +1,4 @@ -import _ from "underscore"; +import _ from "lodash"; // The following constants are tuned to work with // TYPING_STARTED_EXPIRY_PERIOD, which is what the other diff --git a/static/shared/package.json b/static/shared/package.json index c288b88204..26005e5e64 100644 --- a/static/shared/package.json +++ b/static/shared/package.json @@ -4,6 +4,6 @@ "license": "Apache-2.0", "dependencies": { "katex": "^0.12.0", - "underscore": "^1.9.1" + "lodash": "^4.17.19" } } diff --git a/templates/zerver/team.html b/templates/zerver/team.html index 65c3f439b6..c11117be2f 100644 --- a/templates/zerver/team.html +++ b/templates/zerver/team.html @@ -120,7 +120,7 @@
- +