eslint: Fix unicorn/better-regex.

https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/better-regex.md

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg 2020-10-07 03:37:15 -07:00 committed by Tim Abbott
parent a37616e8c6
commit 0042cf51c1
12 changed files with 33 additions and 33 deletions

View File

@ -1487,7 +1487,7 @@ run_test("on_events", () => {
handler(ev); handler(ev);
// video link ids consist of 15 random digits // 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); assert.match(syntax_to_insert, video_link_regex);
page_params.jitsi_server_url = null; page_params.jitsi_server_url = null;
@ -1512,7 +1512,7 @@ run_test("on_events", () => {
}; };
handler(ev); 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); assert.match(syntax_to_insert, video_link_regex);
page_params.realm_video_chat_provider = page_params.realm_video_chat_provider =
@ -1527,7 +1527,7 @@ run_test("on_events", () => {
}; };
handler(ev); 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); assert.match(syntax_to_insert, video_link_regex);
})(); })();

View File

@ -676,19 +676,19 @@ run_test("python_to_js_filter", () => {
// to update_realm_filter_rules. // to update_realm_filter_rules.
markdown.update_realm_filter_rules([["/a(?im)a/g"], ["/a(?L)a/g"]]); markdown.update_realm_filter_rules([["/a(?im)a/g"], ["/a(?L)a/g"]]);
let actual_value = marked.InlineLexer.rules.zulip.realm_filters; 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); assert.deepEqual(actual_value, expected_value);
// Test case with multiple replacements. // Test case with multiple replacements.
markdown.update_realm_filter_rules([ markdown.update_realm_filter_rules([
["#cf(?P<contest>[0-9]+)(?P<problem>[A-Z][0-9A-Z]*)", "http://google.com"], ["#cf(?P<contest>\\d+)(?P<problem>[A-Z][\\dA-Z]*)", "http://google.com"],
]); ]);
actual_value = marked.InlineLexer.rules.zulip.realm_filters; 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); assert.deepEqual(actual_value, expected_value);
// Test incorrect syntax. // Test incorrect syntax.
blueslip.expect( blueslip.expect(
"error", "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"]]); markdown.update_realm_filter_rules([["!@#@(!#&((!&(@#(", "http://google.com"]]);
actual_value = marked.InlineLexer.rules.zulip.realm_filters; actual_value = marked.InlineLexer.rules.zulip.realm_filters;

View File

@ -8,7 +8,7 @@ const common = require("../puppeteer_lib/common");
const OUTGOING_WEBHOOK_BOT_TYPE = "3"; const OUTGOING_WEBHOOK_BOT_TYPE = "3";
const GENERIC_BOT_TYPE = "1"; 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) { async function get_decoded_url_in_selector(page, selector) {
return await page.evaluate( return await page.evaluate(
@ -76,7 +76,7 @@ async function test_get_api_key(page) {
await page.waitForSelector("#show_api_key", {visible: true}); await page.waitForSelector("#show_api_key", {visible: true});
const api_key = await common.get_text_from_selector(page, "#api_key_value"); 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"; const download_zuliprc_selector = "#download_zuliprc";
await page.click(download_zuliprc_selector); 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 bot_email = "1-bot@zulip.testserver";
const download_zuliprc_selector = '.download_bot_zuliprc[data-email="' + bot_email + '"]'; 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.waitForSelector(download_zuliprc_selector, {visible: true});
await page.click(download_zuliprc_selector); await page.click(download_zuliprc_selector);
@ -137,7 +137,7 @@ async function test_botserverrc(page) {
page, page,
"#download_botserverrc", "#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."); assert(botserverrc_regex.test(botserverrc_decoded_url), "Incorrect botserverrc format.");
} }

View File

@ -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)); 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()); search_terms = search_terms.map((s) => s.trim());
const persons = user_ids.map((user_id) => people.get_by_user_id(user_id)); const persons = user_ids.map((user_id) => people.get_by_user_id(user_id));

View File

@ -100,7 +100,7 @@ exports.copy_data_attribute_value = function (elem, key) {
}; };
exports.has_mac_keyboard = function () { 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) { exports.adjust_mac_shortcuts = function (key_elem_class, require_cmd_style) {

View File

@ -278,7 +278,7 @@ exports.tokenize_compose_str = function (s) {
case "_": case "_":
if (i === 0) { if (i === 0) {
return s; return s;
} else if (/[\s(){}[\]]/.test(s[i - 1])) { } else if (/[\s()[\]{}]/.test(s[i - 1])) {
return s.slice(i); return s.slice(i);
} }
break; break;
@ -612,7 +612,7 @@ exports.get_candidates = function (query) {
// as :P or :-p // as :P or :-p
// Also, if the user has only typed a colon and nothing after, // Also, if the user has only typed a colon and nothing after,
// no need to match yet. // 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; return false;
} }
// Don't autocomplete if there is a space following a ':' // Don't autocomplete if there is a space following a ':'

View File

@ -317,7 +317,7 @@ exports.paste_handler = function (event) {
const paste_html = clipboardData.getData("text/html"); const paste_html = clipboardData.getData("text/html");
if (paste_html && page_params.development_environment) { if (paste_html && page_params.development_environment) {
const text = exports.paste_handler_converter(paste_html); const text = exports.paste_handler_converter(paste_html);
const mdImageRegex = /^!\[.*\]\(.*\)$/; const mdImageRegex = /^!\[.*]\(.*\)$/;
if (text.match(mdImageRegex)) { if (text.match(mdImageRegex)) {
// This block catches cases where we are pasting an // This block catches cases where we are pasting an
// image into Zulip, which is handled by upload.js. // image into Zulip, which is handled by upload.js.

View File

@ -30,12 +30,12 @@ const backend_only_markdown_re = [
// Inline image previews, check for contiguous chars ending in image suffix // 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 // 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)\)?\s+/m,
/[^\s]*(?:(?:\.bmp|\.gif|\.jpg|\.jpeg|\.png|\.webp)\)?)$/m, /\S*(?:\.bmp|\.gif|\.jpg|\.jpeg|\.png|\.webp)\)?$/m,
// Twitter and youtube links are given previews // Twitter and youtube links are given previews
/[^\s]*(?:twitter|youtube).com\/[^\s]*/, /\S*(?:twitter|youtube).com\/\S*/,
]; ];
exports.translate_emoticons_to_names = (text) => { 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 // then don't render it locally. It is workaround for the fact that
// javascript regex doesn't support lookbehind. // javascript regex doesn't support lookbehind.
const false_filter_match = realm_filter_list.find((re) => { 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); const regex = new RegExp(pattern);
return regex.test(content); return regex.test(content);
}); });
@ -237,7 +237,7 @@ exports.add_topic_links = function (message) {
} }
// Also make raw urls navigable // 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); const match = topic.match(url_re);
if (match) { if (match) {
links = links.concat(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 // Convert any python in-regex flags to RegExp flags
let js_flags = "g"; let js_flags = "g";
const inline_flag_re = /\(\?([iLmsux]+)\)/; const inline_flag_re = /\(\?([Limsux]+)\)/;
match = inline_flag_re.exec(pattern); match = inline_flag_re.exec(pattern);
// JS regexes only support i (case insensitivity) and m (multiline) // 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 // is rendered locally, otherwise, we return false there and
// message is rendered on the backend which has proper support // message is rendered on the backend which has proper support
// for negative lookbehind. // for negative lookbehind.
pattern = pattern + /(?![\w])/.source; pattern = pattern + /(?!\w)/.source;
let final_regex = null; let final_regex = null;
try { try {
final_regex = new RegExp(pattern, js_flags); 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_markdown_regex(marked.Lexer.rules.tables, "lheading");
// Disable __strong__ (keeping **strong**) // Disable __strong__ (keeping **strong**)
marked.InlineLexer.rules.zulip.strong = /^\*\*([\s\S]+?)\*\*(?!\*)/; marked.InlineLexer.rules.zulip.strong = /^\*\*([\S\s]+?)\*\*(?!\*)/;
// Make sure <del> syntax matches the backend processor // Make sure <del> syntax matches the backend processor
marked.InlineLexer.rules.zulip.del = /^(?!<~)~~([^~]+)~~(?!~)/; marked.InlineLexer.rules.zulip.del = /^(?!<~)~~([^~]+)~~(?!~)/;
@ -545,7 +545,7 @@ exports.initialize = function (realm_filters, helper_config) {
// Disable _emphasis_ (keeping *emphasis*) // Disable _emphasis_ (keeping *emphasis*)
// Text inside ** must start and end with a word character // Text inside ** must start and end with a word character
// to prevent mis-parsing things like "char **x = (char **)y" // 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 autolink as (a) it is not used in our backend and (b) it interferes with @mentions
disable_markdown_regex(marked.InlineLexer.rules.zulip, "autolink"); disable_markdown_regex(marked.InlineLexer.rules.zulip, "autolink");

View File

@ -1,17 +1,17 @@
export function detect_user_os() { export function detect_user_os() {
if (/Android/i.test(navigator.userAgent)) { if (/android/i.test(navigator.userAgent)) {
return "android"; return "android";
} }
if (/iPhone|iPad|iPod/i.test(navigator.userAgent)) { if (/iphone|ipad|ipod/i.test(navigator.userAgent)) {
return "ios"; return "ios";
} }
if (common.has_mac_keyboard()) { if (common.has_mac_keyboard()) {
return "mac"; return "mac";
} }
if (/Win/i.test(navigator.userAgent)) { if (/win/i.test(navigator.userAgent)) {
return "windows"; return "windows";
} }
if (/Linux/i.test(navigator.userAgent)) { if (/linux/i.test(navigator.userAgent)) {
return "linux"; return "linux";
} }
return "mac"; // if unable to determine OS return Mac by default return "mac"; // if unable to determine OS return Mac by default

View File

@ -68,7 +68,7 @@ function is_local_part(value, element) {
// Adapted from Django's EmailValidator // Adapted from Django's EmailValidator
return ( return (
this.optional(element) || this.optional(element) ||
/^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*$/i.test(value) /^[\w!#$%&'*+/=?^`{|}~-]+(\.[\w!#$%&'*+/=?^`{|}~-]+)*$/i.test(value)
); );
} }

View File

@ -154,13 +154,13 @@ exports.get_color_class = _.memoize((color) => {
const channel = [0, 0, 0]; const channel = [0, 0, 0];
let mult = 1; 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) { if (!match) {
// 3-digit shorthand; Spectrum gives this e.g. for pure black. // 3-digit shorthand; Spectrum gives this e.g. for pure black.
// Multiply each digit by 16+1. // Multiply each digit by 16+1.
mult = 17; 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) { if (!match) {
// Can't understand color. // Can't understand color.
return ""; return "";

View File

@ -315,7 +315,7 @@ exports.slug_to_name = function (slug) {
GitHub conversations. We migrated to modern slugs in GitHub conversations. We migrated to modern slugs in
early 2018. early 2018.
*/ */
const m = /^([\d]+)(-.*)?/.exec(slug); const m = /^(\d+)(-.*)?/.exec(slug);
if (m) { if (m) {
const stream_id = Number.parseInt(m[1], 10); const stream_id = Number.parseInt(m[1], 10);
const sub = subs_by_stream_id.get(stream_id); const sub = subs_by_stream_id.get(stream_id);