From 2f9326baac015decb94feab8333fbef8e22b726c Mon Sep 17 00:00:00 2001 From: danrahn Date: Sat, 4 Mar 2023 12:43:46 -0800 Subject: [PATCH] Use named regex capture groups Add eslint rule requiring named capture groups for better regex clarity. --- .eslintrc.json | 1 + Client/Script/PlexClientState.js | 8 ++++---- Client/Script/VersionManager.js | 16 ++++++++-------- Client/Script/inc/Animate.js | 10 +++++----- Shared/ConsoleLog.js | 8 ++++---- Shared/MarkerBreakdown.js | 4 ++-- 6 files changed, 24 insertions(+), 23 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 801ea32..eadeeeb 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -37,6 +37,7 @@ { "blankLine": "any", "prev": "*", "next": "case" }, { "blankLine": "any", "prev": "*", "next": "default" }], "prefer-const" : "error", + "prefer-named-capture-group" : "error", "prefer-regex-literals" : "error", "quote-props" : ["error", "as-needed"], "quotes": ["error", "single", { "avoidEscape" : true, "allowTemplateLiterals" : true }], diff --git a/Client/Script/PlexClientState.js b/Client/Script/PlexClientState.js index 4d49c5d..39988f0 100644 --- a/Client/Script/PlexClientState.js +++ b/Client/Script/PlexClientState.js @@ -306,14 +306,14 @@ class PlexClientStateManager { async search(query) { let regexp = undefined; // Not a perfect test, but close enough - const match = /^\/(.+)\/(g?i?d?y?)$/.exec(query); + const match = /^\/(?.+)\/(?g?i?d?y?)$/.exec(query); if (match) { - regexp = new RegExp(match[1], match[2]); + regexp = new RegExp(match.groups.regex, match.groups.modifiers); } // For movies, also try matching any year that's present. - let queryYear = /\b(1[8-9]\d{2}|20\d{2})\b/.exec(query); - if (queryYear) { queryYear = queryYear[1]; } + let queryYear = /\b(?1[8-9]\d{2}|20\d{2})\b/.exec(query); + if (queryYear) { queryYear = queryYear.groups.year; } // Ignore non-word characters to improve matching if there are spacing or quote mismatches. // Don't use \W though, since that also clears out unicode characters. Rather than import diff --git a/Client/Script/VersionManager.js b/Client/Script/VersionManager.js index 4c2737d..8e94715 100644 --- a/Client/Script/VersionManager.js +++ b/Client/Script/VersionManager.js @@ -216,7 +216,7 @@ class Version { * * `alpha` * * `beta` * * `rc.0`, where 0 is any number with 1 or more digits */ - static #versionRegex = /^v?(\d+)\.(\d+)\.(\d+)(?:-(alpha|beta|rc\.(\d+)))?/; + static #versionRegex = /^v?(?\d+)\.(?\d+)\.(?\d+)(?:-(?alpha|beta|rc\.(?\d+)))?/; /** * Compare two `Version`s, ordering from smallest to largest @@ -272,11 +272,11 @@ class Version { return; } - this.major = parseInt(parts[1]); - this.minor = parseInt(parts[2]); - this.patch = parseInt(parts[3]); - if (parts[4]) { - const partLower = parts[4].toLowerCase(); + this.major = parseInt(parts.groups.major); + this.minor = parseInt(parts.groups.minor); + this.patch = parseInt(parts.groups.patch); + if (parts.groups.type) { + const partLower = parts.groups.type.toLowerCase(); switch (partLower) { case 'alpha': this.releaseTypeInfo.type = PrereleaseType.Alpha; @@ -286,11 +286,11 @@ class Version { break; default: Log.assert( - partLower.startsWith('rc') && parts[5], + partLower.startsWith('rc') && parts.groups.rcVersion, `Version: Expected rc with a valid rc number if not alpha or beta, found ${partLower}.`); this.releaseTypeInfo.type = PrereleaseType.ReleaseCandidate; - this.releaseTypeInfo.rcVersion = parseInt(parts[5]); + this.releaseTypeInfo.rcVersion = parseInt(parts.groups.rcVersion); break; } } diff --git a/Client/Script/inc/Animate.js b/Client/Script/inc/Animate.js index b675d9d..57906bd 100644 --- a/Client/Script/inc/Animate.js +++ b/Client/Script/inc/Animate.js @@ -312,12 +312,12 @@ function Color(r, g, b, a) { } // Assume rgb string - const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i.exec(r); + const result = /^#?(?[a-f\d]{2})(?[a-f\d]{2})(?[a-f\d]{2})(?[a-f\d]{2})?$/i.exec(r); - this.r = parse(result[1], 16); - this.g = parse(result[2], 16); - this.b = parse(result[3], 16); - this.a = result[4] ? (parse(result[4], 16) / 255): 1; + this.r = parse(result.groups.red, 16); + this.g = parse(result.groups.green, 16); + this.b = parse(result.groups.blue, 16); + this.a = result.groups.alpha ? (parse(result.groups.alpha, 16) / 255) : 1; } else { if (g === undefined) { // Hacky to keep the trailing parenthesis, but parseInt/Float figures it out diff --git a/Shared/ConsoleLog.js b/Shared/ConsoleLog.js index 5770424..667139a 100644 --- a/Shared/ConsoleLog.js +++ b/Shared/ConsoleLog.js @@ -186,10 +186,10 @@ class ConsoleLog { * @param {string} logString * @param {number} levelDefault The default level if we are unable to parse the logString. */ setFromString(logString, levelDefault=ConsoleLog.Level.Info) { - const match = /(trace)?(dark)?(extreme|tmi|verbose|info|warn|error|critical)?/i.exec(logString); - this.setTrace(match[1] ? 1 : 0); - this.setDarkConsole(match[2] ? 1 : 0); - let level = match[3] ? ConsoleLog.#logStrings.indexOf(match[3].toUpperCase()) : ConsoleLog.Level.Invalid; + const match = /(?trace)?(?dark)?(?extreme|tmi|verbose|info|warn|error|critical)?/i.exec(logString); + this.setTrace(match.groups.t ? 1 : 0); + this.setDarkConsole(match.groups.d ? 1 : 0); + let level = match.groups.l ? ConsoleLog.#logStrings.indexOf(match.groups.l.toUpperCase()) : ConsoleLog.Level.Invalid; if (level == ConsoleLog.Level.Invalid) { console.warn( `[WARN][${ConsoleLog.#getTimestring()}] ` + diff --git a/Shared/MarkerBreakdown.js b/Shared/MarkerBreakdown.js index e94d184..3965f76 100644 --- a/Shared/MarkerBreakdown.js +++ b/Shared/MarkerBreakdown.js @@ -23,8 +23,8 @@ class MarkerBreakdown { case MarkerType.Credits: return delta << CreditsShift; default: - // Unexpected, but just log an error and treat it as an intro. - Log.error(`Invalid marker type ${markerType}`); + // Silently fall back to an intro + Log.error(`Invalid marker type "${markerType}"`); return delta; } }