diff --git a/frontend_tests/node_tests/compose.js b/frontend_tests/node_tests/compose.js index 760650540d..f310cbb2a4 100644 --- a/frontend_tests/node_tests/compose.js +++ b/frontend_tests/node_tests/compose.js @@ -1487,7 +1487,7 @@ run_test("on_events", () => { handler(ev); // video link ids consist of 15 random digits - let video_link_regex = /\[translated: Click to join video call\]\(https:\/\/meet.jit.si\/\d{15}\)/; + let video_link_regex = /\[translated: Click to join video call]\(https:\/\/meet.jit.si\/\d{15}\)/; assert.match(syntax_to_insert, video_link_regex); page_params.jitsi_server_url = null; @@ -1512,7 +1512,7 @@ run_test("on_events", () => { }; handler(ev); - video_link_regex = /\[translated: Click to join video call\]\(example\.zoom\.com\)/; + video_link_regex = /\[translated: Click to join video call]\(example\.zoom\.com\)/; assert.match(syntax_to_insert, video_link_regex); page_params.realm_video_chat_provider = @@ -1527,7 +1527,7 @@ run_test("on_events", () => { }; handler(ev); - video_link_regex = /\[translated: Click to join video call\]\(\/calls\/bigbluebutton\/join\?meeting_id=%22zulip-1%22&password=%22AAAAAAAAAA%22&checksum=%2232702220bff2a22a44aee72e96cfdb4c4091752e%22\)/; + video_link_regex = /\[translated: Click to join video call]\(\/calls\/bigbluebutton\/join\?meeting_id=%22zulip-1%22&password=%22AAAAAAAAAA%22&checksum=%2232702220bff2a22a44aee72e96cfdb4c4091752e%22\)/; assert.match(syntax_to_insert, video_link_regex); })(); diff --git a/frontend_tests/node_tests/markdown.js b/frontend_tests/node_tests/markdown.js index ce8b1f4bd4..c815311b3c 100644 --- a/frontend_tests/node_tests/markdown.js +++ b/frontend_tests/node_tests/markdown.js @@ -676,19 +676,19 @@ run_test("python_to_js_filter", () => { // to update_realm_filter_rules. markdown.update_realm_filter_rules([["/a(?im)a/g"], ["/a(?L)a/g"]]); let actual_value = marked.InlineLexer.rules.zulip.realm_filters; - let expected_value = [/\/aa\/g(?![\w])/gim, /\/aa\/g(?![\w])/g]; + let expected_value = [/\/aa\/g(?!\w)/gim, /\/aa\/g(?!\w)/g]; assert.deepEqual(actual_value, expected_value); // Test case with multiple replacements. markdown.update_realm_filter_rules([ - ["#cf(?P[0-9]+)(?P[A-Z][0-9A-Z]*)", "http://google.com"], + ["#cf(?P\\d+)(?P[A-Z][\\dA-Z]*)", "http://google.com"], ]); actual_value = marked.InlineLexer.rules.zulip.realm_filters; - expected_value = [/#cf([0-9]+)([A-Z][0-9A-Z]*)(?![\w])/g]; + expected_value = [/#cf(\d+)([A-Z][\dA-Z]*)(?!\w)/g]; assert.deepEqual(actual_value, expected_value); // Test incorrect syntax. blueslip.expect( "error", - "python_to_js_filter: Invalid regular expression: /!@#@(!#&((!&(@#((?![\\w])/: Unterminated group", + "python_to_js_filter: Invalid regular expression: /!@#@(!#&((!&(@#((?!\\w)/: Unterminated group", ); markdown.update_realm_filter_rules([["!@#@(!#&((!&(@#(", "http://google.com"]]); actual_value = marked.InlineLexer.rules.zulip.realm_filters; diff --git a/frontend_tests/puppeteer_tests/16-settings.js b/frontend_tests/puppeteer_tests/16-settings.js index bcf5fe895e..b7a03c93be 100644 --- a/frontend_tests/puppeteer_tests/16-settings.js +++ b/frontend_tests/puppeteer_tests/16-settings.js @@ -8,7 +8,7 @@ const common = require("../puppeteer_lib/common"); const OUTGOING_WEBHOOK_BOT_TYPE = "3"; const GENERIC_BOT_TYPE = "1"; -const zuliprc_regex = /^data:application\/octet-stream;charset=utf-8,\[api\]\nemail=.+\nkey=.+\nsite=.+\n$/; +const zuliprc_regex = /^data:application\/octet-stream;charset=utf-8,\[api]\nemail=.+\nkey=.+\nsite=.+\n$/; async function get_decoded_url_in_selector(page, selector) { return await page.evaluate( @@ -76,7 +76,7 @@ async function test_get_api_key(page) { await page.waitForSelector("#show_api_key", {visible: true}); const api_key = await common.get_text_from_selector(page, "#api_key_value"); - assert(/[a-zA-Z0-9]{32}/.test(api_key), "Incorrect API key format."); + assert(/[\dA-Za-z]{32}/.test(api_key), "Incorrect API key format."); const download_zuliprc_selector = "#download_zuliprc"; await page.click(download_zuliprc_selector); @@ -97,7 +97,7 @@ async function test_webhook_bot_creation(page) { const bot_email = "1-bot@zulip.testserver"; const download_zuliprc_selector = '.download_bot_zuliprc[data-email="' + bot_email + '"]'; - const outgoing_webhook_zuliprc_regex = /^data:application\/octet-stream;charset=utf-8,\[api\]\nemail=.+\nkey=.+\nsite=.+\ntoken=.+\n$/; + const outgoing_webhook_zuliprc_regex = /^data:application\/octet-stream;charset=utf-8,\[api]\nemail=.+\nkey=.+\nsite=.+\ntoken=.+\n$/; await page.waitForSelector(download_zuliprc_selector, {visible: true}); await page.click(download_zuliprc_selector); @@ -137,7 +137,7 @@ async function test_botserverrc(page) { page, "#download_botserverrc", ); - const botserverrc_regex = /^data:application\/octet-stream;charset=utf-8,\[\]\nemail=.+\nkey=.+\nsite=.+\ntoken=.+\n$/; + const botserverrc_regex = /^data:application\/octet-stream;charset=utf-8,\[]\nemail=.+\nkey=.+\nsite=.+\ntoken=.+\n$/; assert(botserverrc_regex.test(botserverrc_decoded_url), "Incorrect botserverrc format."); } diff --git a/static/js/buddy_data.js b/static/js/buddy_data.js index ba15d8781f..eeefdc92f6 100644 --- a/static/js/buddy_data.js +++ b/static/js/buddy_data.js @@ -121,7 +121,7 @@ function filter_user_ids(user_filter_text, user_ids) { user_ids = user_ids.filter((user_id) => !people.is_my_user_id(user_id)); - let search_terms = user_filter_text.toLowerCase().split(/[|,]+/); + let search_terms = user_filter_text.toLowerCase().split(/[,|]+/); search_terms = search_terms.map((s) => s.trim()); const persons = user_ids.map((user_id) => people.get_by_user_id(user_id)); diff --git a/static/js/common.js b/static/js/common.js index 0e36c70d91..b6593d1077 100644 --- a/static/js/common.js +++ b/static/js/common.js @@ -100,7 +100,7 @@ exports.copy_data_attribute_value = function (elem, key) { }; exports.has_mac_keyboard = function () { - return /Mac/i.test(navigator.platform); + return /mac/i.test(navigator.platform); }; exports.adjust_mac_shortcuts = function (key_elem_class, require_cmd_style) { diff --git a/static/js/composebox_typeahead.js b/static/js/composebox_typeahead.js index 33b7ca14c9..23cd5446aa 100644 --- a/static/js/composebox_typeahead.js +++ b/static/js/composebox_typeahead.js @@ -278,7 +278,7 @@ exports.tokenize_compose_str = function (s) { case "_": if (i === 0) { return s; - } else if (/[\s(){}[\]]/.test(s[i - 1])) { + } else if (/[\s()[\]{}]/.test(s[i - 1])) { return s.slice(i); } break; @@ -612,7 +612,7 @@ exports.get_candidates = function (query) { // as :P or :-p // Also, if the user has only typed a colon and nothing after, // no need to match yet. - if (/^:-.?$/.test(current_token) || /^:[^a-z+]?$/.test(current_token)) { + if (/^:-.?$/.test(current_token) || /^:[^+a-z]?$/.test(current_token)) { return false; } // Don't autocomplete if there is a space following a ':' diff --git a/static/js/copy_and_paste.js b/static/js/copy_and_paste.js index 9557ac8d76..649ee2d1d3 100644 --- a/static/js/copy_and_paste.js +++ b/static/js/copy_and_paste.js @@ -317,7 +317,7 @@ exports.paste_handler = function (event) { const paste_html = clipboardData.getData("text/html"); if (paste_html && page_params.development_environment) { const text = exports.paste_handler_converter(paste_html); - const mdImageRegex = /^!\[.*\]\(.*\)$/; + const mdImageRegex = /^!\[.*]\(.*\)$/; if (text.match(mdImageRegex)) { // This block catches cases where we are pasting an // image into Zulip, which is handled by upload.js. diff --git a/static/js/markdown.js b/static/js/markdown.js index 0a78eef99d..ea0bcdef8c 100644 --- a/static/js/markdown.js +++ b/static/js/markdown.js @@ -30,12 +30,12 @@ const backend_only_markdown_re = [ // Inline image previews, check for contiguous chars ending in image suffix // To keep the below regexes simple, split them out for the end-of-message case - /[^\s]*(?:(?:\.bmp|\.gif|\.jpg|\.jpeg|\.png|\.webp)\)?)\s+/m, - /[^\s]*(?:(?:\.bmp|\.gif|\.jpg|\.jpeg|\.png|\.webp)\)?)$/m, + /\S*(?:\.bmp|\.gif|\.jpg|\.jpeg|\.png|\.webp)\)?\s+/m, + /\S*(?:\.bmp|\.gif|\.jpg|\.jpeg|\.png|\.webp)\)?$/m, // Twitter and youtube links are given previews - /[^\s]*(?:twitter|youtube).com\/[^\s]*/, + /\S*(?:twitter|youtube).com\/\S*/, ]; exports.translate_emoticons_to_names = (text) => { @@ -88,7 +88,7 @@ exports.contains_backend_only_syntax = function (content) { // then don't render it locally. It is workaround for the fact that // javascript regex doesn't support lookbehind. const false_filter_match = realm_filter_list.find((re) => { - const pattern = /(?:[^\s'"(,:<])/.source + re[0].source + /(?![\w])/.source; + const pattern = /[^\s"'(,:<]/.source + re[0].source + /(?!\w)/.source; const regex = new RegExp(pattern); return regex.test(content); }); @@ -237,7 +237,7 @@ exports.add_topic_links = function (message) { } // Also make raw urls navigable - const url_re = /\b(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/g; // Slightly modified from third/marked.js + const url_re = /\b(https?:\/\/[^\s<]+[^\s"'),.:;<\]])/g; // Slightly modified from third/marked.js const match = topic.match(url_re); if (match) { links = links.concat(match); @@ -432,7 +432,7 @@ function python_to_js_filter(pattern, url) { } // Convert any python in-regex flags to RegExp flags let js_flags = "g"; - const inline_flag_re = /\(\?([iLmsux]+)\)/; + const inline_flag_re = /\(\?([Limsux]+)\)/; match = inline_flag_re.exec(pattern); // JS regexes only support i (case insensitivity) and m (multiline) @@ -456,7 +456,7 @@ function python_to_js_filter(pattern, url) { // is rendered locally, otherwise, we return false there and // message is rendered on the backend which has proper support // for negative lookbehind. - pattern = pattern + /(?![\w])/.source; + pattern = pattern + /(?!\w)/.source; let final_regex = null; try { final_regex = new RegExp(pattern, js_flags); @@ -537,7 +537,7 @@ exports.initialize = function (realm_filters, helper_config) { disable_markdown_regex(marked.Lexer.rules.tables, "lheading"); // Disable __strong__ (keeping **strong**) - marked.InlineLexer.rules.zulip.strong = /^\*\*([\s\S]+?)\*\*(?!\*)/; + marked.InlineLexer.rules.zulip.strong = /^\*\*([\S\s]+?)\*\*(?!\*)/; // Make sure syntax matches the backend processor marked.InlineLexer.rules.zulip.del = /^(?!<~)~~([^~]+)~~(?!~)/; @@ -545,7 +545,7 @@ exports.initialize = function (realm_filters, helper_config) { // Disable _emphasis_ (keeping *emphasis*) // Text inside ** must start and end with a word character // to prevent mis-parsing things like "char **x = (char **)y" - marked.InlineLexer.rules.zulip.em = /^\*(?!\s+)((?:\*\*|[\s\S])+?)((?:[\S]))\*(?!\*)/; + marked.InlineLexer.rules.zulip.em = /^\*(?!\s+)((?:\*\*|[\S\s])+?)(\S)\*(?!\*)/; // Disable autolink as (a) it is not used in our backend and (b) it interferes with @mentions disable_markdown_regex(marked.InlineLexer.rules.zulip, "autolink"); diff --git a/static/js/portico/tabbed-instructions.js b/static/js/portico/tabbed-instructions.js index de6a003dc4..4649a27261 100644 --- a/static/js/portico/tabbed-instructions.js +++ b/static/js/portico/tabbed-instructions.js @@ -1,17 +1,17 @@ export function detect_user_os() { - if (/Android/i.test(navigator.userAgent)) { + if (/android/i.test(navigator.userAgent)) { return "android"; } - if (/iPhone|iPad|iPod/i.test(navigator.userAgent)) { + if (/iphone|ipad|ipod/i.test(navigator.userAgent)) { return "ios"; } if (common.has_mac_keyboard()) { return "mac"; } - if (/Win/i.test(navigator.userAgent)) { + if (/win/i.test(navigator.userAgent)) { return "windows"; } - if (/Linux/i.test(navigator.userAgent)) { + if (/linux/i.test(navigator.userAgent)) { return "linux"; } return "mac"; // if unable to determine OS return Mac by default diff --git a/static/js/settings_bots.js b/static/js/settings_bots.js index 6c4850ea0e..d3a494e224 100644 --- a/static/js/settings_bots.js +++ b/static/js/settings_bots.js @@ -68,7 +68,7 @@ function is_local_part(value, element) { // Adapted from Django's EmailValidator return ( this.optional(element) || - /^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*$/i.test(value) + /^[\w!#$%&'*+/=?^`{|}~-]+(\.[\w!#$%&'*+/=?^`{|}~-]+)*$/i.test(value) ); } diff --git a/static/js/stream_color.js b/static/js/stream_color.js index 01f04d5fe5..932ff1d1e7 100644 --- a/static/js/stream_color.js +++ b/static/js/stream_color.js @@ -154,13 +154,13 @@ exports.get_color_class = _.memoize((color) => { const channel = [0, 0, 0]; let mult = 1; - match = /^#([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})$/.exec(color); + match = /^#([\dA-Fa-f]{2})([\dA-Fa-f]{2})([\dA-Fa-f]{2})$/.exec(color); if (!match) { // 3-digit shorthand; Spectrum gives this e.g. for pure black. // Multiply each digit by 16+1. mult = 17; - match = /^#([\da-fA-F])([\da-fA-F])([\da-fA-F])$/.exec(color); + match = /^#([\dA-Fa-f])([\dA-Fa-f])([\dA-Fa-f])$/.exec(color); if (!match) { // Can't understand color. return ""; diff --git a/static/js/stream_data.js b/static/js/stream_data.js index eaa7d33ddc..cfa07a94f7 100644 --- a/static/js/stream_data.js +++ b/static/js/stream_data.js @@ -315,7 +315,7 @@ exports.slug_to_name = function (slug) { GitHub conversations. We migrated to modern slugs in early 2018. */ - const m = /^([\d]+)(-.*)?/.exec(slug); + const m = /^(\d+)(-.*)?/.exec(slug); if (m) { const stream_id = Number.parseInt(m[1], 10); const sub = subs_by_stream_id.get(stream_id);