From db64d9869ce393030279caa0cdfbd64b327869ad Mon Sep 17 00:00:00 2001 From: Martin Fournier Date: Sat, 18 Dec 2021 16:22:10 -0500 Subject: [PATCH 1/9] Add easily switchable predefined themes Includes the default theme and a Monokai-ish variant --- src/Settings/Settings.ts | 110 +------ src/Settings/Themes.ts | 110 +++++++ src/ui/React/ThemeEditorModal.tsx | 497 ++++++++++++++++-------------- 3 files changed, 373 insertions(+), 344 deletions(-) create mode 100644 src/Settings/Themes.ts diff --git a/src/Settings/Settings.ts b/src/Settings/Settings.ts index 8a4cbdd31..a1cc7d006 100644 --- a/src/Settings/Settings.ts +++ b/src/Settings/Settings.ts @@ -1,5 +1,6 @@ import { ISelfInitializer, ISelfLoading } from "../types"; import { OwnedAugmentationsOrderSetting, PurchaseAugmentationsOrderSetting } from "./SettingEnums"; +import { defaultTheme, ITheme } from "./Themes"; /** * Represents the default settings the player could customize. @@ -111,42 +112,7 @@ interface IDefaultSettings { /* * Theme colors */ - theme: { - [key: string]: string | undefined; - primarylight: string; - primary: string; - primarydark: string; - successlight: string; - success: string; - successdark: string; - errorlight: string; - error: string; - errordark: string; - secondarylight: string; - secondary: string; - secondarydark: string; - warninglight: string; - warning: string; - warningdark: string; - infolight: string; - info: string; - infodark: string; - welllight: string; - well: string; - white: string; - black: string; - hp: string; - money: string; - hack: string; - combat: string; - cha: string; - int: string; - rep: string; - disabled: string; - backgroundprimary: string; - backgroundsecondary: string; - button: string; - }; + theme: ITheme; } /** @@ -193,41 +159,7 @@ export const defaultSettings: IDefaultSettings = { SuppressTIXPopup: false, SuppressSavedGameToast: false, - theme: { - primarylight: "#0f0", - primary: "#0c0", - primarydark: "#090", - successlight: "#0f0", - success: "#0c0", - successdark: "#090", - errorlight: "#f00", - error: "#c00", - errordark: "#900", - secondarylight: "#AAA", - secondary: "#888", - secondarydark: "#666", - warninglight: "#ff0", - warning: "#cc0", - warningdark: "#990", - infolight: "#69f", - info: "#36c", - infodark: "#039", - welllight: "#444", - well: "#222", - white: "#fff", - black: "#000", - hp: "#dd3434", - money: "#ffd700", - hack: "#adff2f", - combat: "#faffdf", - cha: "#a671d1", - int: "#6495ed", - rep: "#faffdf", - disabled: "#66cfbc", - backgroundprimary: "#000", - backgroundsecondary: "#000", - button: "#333", - }, + theme: defaultTheme, }; /** @@ -262,41 +194,7 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = { MonacoInsertSpaces: false, MonacoFontSize: 20, - theme: { - primarylight: defaultSettings.theme.primarylight, - primary: defaultSettings.theme.primary, - primarydark: defaultSettings.theme.primarydark, - successlight: defaultSettings.theme.successlight, - success: defaultSettings.theme.success, - successdark: defaultSettings.theme.successdark, - errorlight: defaultSettings.theme.errorlight, - error: defaultSettings.theme.error, - errordark: defaultSettings.theme.errordark, - secondarylight: defaultSettings.theme.secondarylight, - secondary: defaultSettings.theme.secondary, - secondarydark: defaultSettings.theme.secondarydark, - warninglight: defaultSettings.theme.warninglight, - warning: defaultSettings.theme.warning, - warningdark: defaultSettings.theme.warningdark, - infolight: defaultSettings.theme.infolight, - info: defaultSettings.theme.info, - infodark: defaultSettings.theme.infodark, - welllight: defaultSettings.theme.welllight, - well: defaultSettings.theme.well, - white: defaultSettings.theme.white, - black: defaultSettings.theme.black, - hp: defaultSettings.theme.hp, - money: defaultSettings.theme.money, - hack: defaultSettings.theme.hack, - combat: defaultSettings.theme.combat, - cha: defaultSettings.theme.cha, - int: defaultSettings.theme.int, - rep: defaultSettings.theme.rep, - disabled: defaultSettings.theme.disabled, - backgroundprimary: defaultSettings.theme.backgroundprimary, - backgroundsecondary: defaultSettings.theme.backgroundsecondary, - button: defaultSettings.theme.button, - }, + theme: { ...defaultTheme }, init() { Object.assign(Settings, defaultSettings); }, diff --git a/src/Settings/Themes.ts b/src/Settings/Themes.ts new file mode 100644 index 000000000..a67ac4bd7 --- /dev/null +++ b/src/Settings/Themes.ts @@ -0,0 +1,110 @@ +export interface ITheme { + [key: string]: string | undefined; + primarylight: string; + primary: string; + primarydark: string; + successlight: string; + success: string; + successdark: string; + errorlight: string; + error: string; + errordark: string; + secondarylight: string; + secondary: string; + secondarydark: string; + warninglight: string; + warning: string; + warningdark: string; + infolight: string; + info: string; + infodark: string; + welllight: string; + well: string; + white: string; + black: string; + hp: string; + money: string; + hack: string; + combat: string; + cha: string; + int: string; + rep: string; + disabled: string; + backgroundprimary: string; + backgroundsecondary: string; + button: string; +} + +export const defaultTheme: ITheme = { + primarylight: "#0f0", + primary: "#0c0", + primarydark: "#090", + successlight: "#0f0", + success: "#0c0", + successdark: "#090", + errorlight: "#f00", + error: "#c00", + errordark: "#900", + secondarylight: "#AAA", + secondary: "#888", + secondarydark: "#666", + warninglight: "#ff0", + warning: "#cc0", + warningdark: "#990", + infolight: "#69f", + info: "#36c", + infodark: "#039", + welllight: "#444", + well: "#222", + white: "#fff", + black: "#000", + hp: "#dd3434", + money: "#ffd700", + hack: "#adff2f", + combat: "#faffdf", + cha: "#a671d1", + int: "#6495ed", + rep: "#faffdf", + disabled: "#66cfbc", + backgroundprimary: "#000", + backgroundsecondary: "#000", + button: "#333", +}; + +export interface IPredefinedThemes { + 'Default': ITheme; + 'Monokai': ITheme; +} + +export const getPredefinedThemes = (): IPredefinedThemes => ({ + 'Default': defaultTheme, + 'Monokai': { + ...defaultTheme, + + backgroundprimary: '#272822', + backgroundsecondary: '#1B1C18', + primary: '#F8F8F2', + primarylight: '#FFF', + primarydark: '#FAFAEB', + success: '#A6E22E', + successlight: '#ADE146', + successdark: '#98E104', + error: '#F92672', + errorlight: '#FF69A0', + errordark: '#D10F56', + warning: '#E6DB74', + warninglight: '#E1D992', + warningdark: '#EDDD54', + info: '#66D9EF', + infolight: '#92E1F1', + infodark: '#31CDED', + + hp: '#F92672', + money: '#E6DB74', + hack: '#A6E22E', + combat: '#75715E', + cha: '#AE81FF', + int: '#66D9EF', + rep: '#E69F66', + } +}); diff --git a/src/ui/React/ThemeEditorModal.tsx b/src/ui/React/ThemeEditorModal.tsx index b8b1f204d..6582ea377 100644 --- a/src/ui/React/ThemeEditorModal.tsx +++ b/src/ui/React/ThemeEditorModal.tsx @@ -7,9 +7,11 @@ import Paper from "@mui/material/Paper"; import TextField from "@mui/material/TextField"; import IconButton from "@mui/material/IconButton"; import ReplyIcon from "@mui/icons-material/Reply"; +import PaletteSharpIcon from "@mui/icons-material/PaletteSharp"; import { Color, ColorPicker } from "material-ui-color"; import { ThemeEvents } from "./Theme"; import { Settings, defaultSettings } from "../../Settings/Settings"; +import { ITheme, getPredefinedThemes } from "../../Settings/Themes"; interface IProps { open: boolean; @@ -64,11 +66,18 @@ export function ThemeEditorModal(props: IProps): React.ReactElement { ...Settings.theme, }); - function resetTheme(): void { - setCustomTheme({ - ...defaultSettings.theme, - }); - Object.assign(Settings.theme, defaultSettings.theme); + const predefinedThemes = getPredefinedThemes(); + const themes = predefinedThemes && Object.entries(predefinedThemes) + .map(([name, templateTheme]) => ( + + )) || <>; + + function setTheme(theme: ITheme): void { + setCustomTheme(theme); + Object.assign(Settings.theme, theme); ThemeEvents.emit(); } @@ -96,250 +105,262 @@ export function ThemeEditorModal(props: IProps): React.ReactElement { ThemeEvents.emit(); } + function setTemplateTheme(theme: ITheme): void { + setTheme(theme); + } + return ( - - Example tooltip}> - - - - - - - - text with primary color - text with secondary color - text with error color - + + Example tooltip}> + + + + + + + + +
+ text with primary color  + text with secondary color  + text with error color + +
+
-
- - - -
+ + + + - - - +
+ + + -
- - - +
+ + + -
- - - +
+ + + -
- - - +
+ + + -
- - - +
+ + + -
- - - - - - - +
+ + + + + + + -
- - - - - - - - -
-
- - - - ), - }} - /> +
+ + + + + + + + +
+ + + + <> + Copy the string above if you want to backup or share your theme with others. + Use the buttons below to replace the current theme with a pre-built template + {themes} + +
); } From 1f6954b393fb84fc34f096befd92eaf080a4b5a6 Mon Sep 17 00:00:00 2001 From: Dan Date: Sun, 19 Dec 2021 02:09:47 +0000 Subject: [PATCH 2/9] fix(command:alias) allow hyphen in aliases - Allow hyphens in aliases - Remove redundant underscore, covered by '\w' Resolves danielyxie/bitburner#2000 --- src/Alias.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Alias.ts b/src/Alias.ts index 73029f69b..b80aed6a3 100644 --- a/src/Alias.ts +++ b/src/Alias.ts @@ -36,7 +36,7 @@ export function printAliases(): void { // Returns true if successful, false otherwise export function parseAliasDeclaration(dec: string, global = false): boolean { - const re = /^([_|\w|!|%|,|@]+)="(.+)"$/; + const re = /^([\w|!|%|,|@|-]+)="(.+)"$/; const matches = dec.match(re); if (matches == null || matches.length != 3) { return false; From 24c7fb2b9218a4be2be99f907d68c512d35c06fa Mon Sep 17 00:00:00 2001 From: Dan Date: Sun, 19 Dec 2021 02:41:21 +0000 Subject: [PATCH 3/9] fix(cli:run) case insensitive calls to program run Allow the user to run programs (.exe) in a case insensitive manor Resolves danielyxie/bitburner#1958 --- src/Terminal/commands/runProgram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Terminal/commands/runProgram.ts b/src/Terminal/commands/runProgram.ts index f9e17b2d8..5f48029e6 100644 --- a/src/Terminal/commands/runProgram.ts +++ b/src/Terminal/commands/runProgram.ts @@ -33,7 +33,7 @@ export function runProgram( } for (const program of Object.values(Programs)) { - if (program.name === programName) { + if (program.name.toLocaleLowerCase() === programName.toLocaleLowerCase()) { program.run( router, terminal, From b2add6c26bc90c1181ae9902cc2bdcf70669d318 Mon Sep 17 00:00:00 2001 From: Dan Date: Sun, 19 Dec 2021 03:10:43 +0000 Subject: [PATCH 4/9] fix(commands): error feedback, wording consistency Found most (hopefully all) places where the error message wording incorrectly was shown to the tune of 'no script exists', where it should have been showing to the effect of 'script is not running'. Also cleaned up some of the consistency in the wording and added a 'helper' export for knowing valid script extensions used in validation of 'isScriptFilename', so we can have consistent error messaging. Resolves danielyxie/bitburner#1966 --- src/Script/isScriptFilename.ts | 4 +++- src/Terminal/commands/check.ts | 12 +++++++----- src/Terminal/commands/kill.ts | 2 +- src/Terminal/commands/mem.ts | 2 +- src/Terminal/commands/scp.ts | 2 +- src/Terminal/commands/tail.ts | 8 ++++---- 6 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/Script/isScriptFilename.ts b/src/Script/isScriptFilename.ts index 3506828e6..b7f13b174 100644 --- a/src/Script/isScriptFilename.ts +++ b/src/Script/isScriptFilename.ts @@ -1,3 +1,5 @@ +export const validScriptExtensions: Array = [`.js`, `.script`, `.ns`]; + export function isScriptFilename(f: string): boolean { - return f.endsWith(".js") || f.endsWith(".script") || f.endsWith(".ns"); + return validScriptExtensions.some((ext) => f.endsWith(ext)); } diff --git a/src/Terminal/commands/check.ts b/src/Terminal/commands/check.ts index be734864a..8cb9e12e7 100644 --- a/src/Terminal/commands/check.ts +++ b/src/Terminal/commands/check.ts @@ -3,7 +3,7 @@ import { IRouter } from "../../ui/Router"; import { IPlayer } from "../../PersonObjects/IPlayer"; import { BaseServer } from "../../Server/BaseServer"; import { findRunningScript } from "../../Script/ScriptHelpers"; -import { isScriptFilename } from "../../Script/isScriptFilename"; +import { isScriptFilename, validScriptExtensions } from "../../Script/isScriptFilename"; export function check( terminal: ITerminal, @@ -13,19 +13,21 @@ export function check( args: (string | number | boolean)[], ): void { if (args.length < 1) { - terminal.error("Incorrect number of arguments. Usage: check [script] [arg1] [arg2]..."); + terminal.error(`Incorrect number of arguments. Usage: check [script] [arg1] [arg2]...`); } else { const scriptName = terminal.getFilepath(args[0] + ""); // Can only tail script files if (!isScriptFilename(scriptName)) { - terminal.error("tail can only be called on .script files (filename must end with .script)"); + terminal.error( + `'check' can only be called on .script files (filename must end with ${validScriptExtensions.join(", ")})`, + ); return; } - // Check that the script exists on this machine + // Check that the script is running on this machine const runningScript = findRunningScript(scriptName, args.slice(1), server); if (runningScript == null) { - terminal.error("No such script exists"); + terminal.error(`No script named ${scriptName} is not running on the server`); return; } runningScript.displayLog(); diff --git a/src/Terminal/commands/kill.ts b/src/Terminal/commands/kill.ts index b2eca0431..be18d733a 100644 --- a/src/Terminal/commands/kill.ts +++ b/src/Terminal/commands/kill.ts @@ -27,7 +27,7 @@ export function kill( if (res) { terminal.print(`Killing script with PID ${pid}`); } else { - terminal.error(`Failed to kill script with PID ${pid}. No such script exists`); + terminal.error(`Failed to kill script with PID ${pid}. No such script is running`); } return; diff --git a/src/Terminal/commands/mem.ts b/src/Terminal/commands/mem.ts index 799af2181..42abc25ea 100644 --- a/src/Terminal/commands/mem.ts +++ b/src/Terminal/commands/mem.ts @@ -29,7 +29,7 @@ export function mem( const script = terminal.getScript(player, scriptName); if (script == null) { - terminal.error("No such script exists!"); + terminal.error("mem failed. No such script exists!"); return; } diff --git a/src/Terminal/commands/scp.ts b/src/Terminal/commands/scp.ts index f1561d6d4..d5def4d68 100644 --- a/src/Terminal/commands/scp.ts +++ b/src/Terminal/commands/scp.ts @@ -90,7 +90,7 @@ export function scp( } } if (sourceScript == null) { - terminal.error("scp() failed. No such script exists"); + terminal.error("scp failed. No such script exists"); return; } diff --git a/src/Terminal/commands/tail.ts b/src/Terminal/commands/tail.ts index 1773d472f..2250e502a 100644 --- a/src/Terminal/commands/tail.ts +++ b/src/Terminal/commands/tail.ts @@ -3,7 +3,7 @@ import { IRouter } from "../../ui/Router"; import { IPlayer } from "../../PersonObjects/IPlayer"; import { BaseServer } from "../../Server/BaseServer"; import { findRunningScriptByPid } from "../../Script/ScriptHelpers"; -import { isScriptFilename } from "../../Script/isScriptFilename"; +import { isScriptFilename, validScriptExtensions } from "../../Script/isScriptFilename"; import { compareArrays } from "../../utils/helpers/compareArrays"; import { LogBoxEvents } from "../../ui/React/LogBoxManager"; @@ -20,7 +20,7 @@ export function tail( } else if (typeof commandArray[0] === "string") { const scriptName = terminal.getFilepath(commandArray[0]); if (!isScriptFilename(scriptName)) { - terminal.error("tail can only be called on .script, .ns, .js files, or by pid"); + terminal.error(`tail can only be called on ${validScriptExtensions.join(", ")} files, or by pid`); return; } @@ -66,11 +66,11 @@ export function tail( } // if there's no candidate then we just don't know. - terminal.error("No such script exists."); + terminal.error(`No script named ${scriptName} is not running on the server`); } else if (typeof commandArray[0] === "number") { const runningScript = findRunningScriptByPid(commandArray[0], server); if (runningScript == null) { - terminal.error("No such script exists"); + terminal.error(`No script with pid ${commandArray[0]} is not running on the server`); return; } LogBoxEvents.emit(runningScript); From b8b3897e6485cb14d2c61d8321e6202df42bfe3c Mon Sep 17 00:00:00 2001 From: Dan Date: Sun, 19 Dec 2021 03:23:26 +0000 Subject: [PATCH 5/9] fix(commands): tweak wording for consistency --- src/Terminal/commands/check.ts | 2 +- src/Terminal/commands/tail.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Terminal/commands/check.ts b/src/Terminal/commands/check.ts index 8cb9e12e7..6ec67ac6b 100644 --- a/src/Terminal/commands/check.ts +++ b/src/Terminal/commands/check.ts @@ -27,7 +27,7 @@ export function check( // Check that the script is running on this machine const runningScript = findRunningScript(scriptName, args.slice(1), server); if (runningScript == null) { - terminal.error(`No script named ${scriptName} is not running on the server`); + terminal.error(`No script named ${scriptName} is running on the server`); return; } runningScript.displayLog(); diff --git a/src/Terminal/commands/tail.ts b/src/Terminal/commands/tail.ts index 2250e502a..d1101e76a 100644 --- a/src/Terminal/commands/tail.ts +++ b/src/Terminal/commands/tail.ts @@ -20,7 +20,7 @@ export function tail( } else if (typeof commandArray[0] === "string") { const scriptName = terminal.getFilepath(commandArray[0]); if (!isScriptFilename(scriptName)) { - terminal.error(`tail can only be called on ${validScriptExtensions.join(", ")} files, or by pid`); + terminal.error(`tail can only be called on ${validScriptExtensions.join(", ")} files, or by PID`); return; } @@ -66,11 +66,11 @@ export function tail( } // if there's no candidate then we just don't know. - terminal.error(`No script named ${scriptName} is not running on the server`); + terminal.error(`No script named ${scriptName} is running on the server`); } else if (typeof commandArray[0] === "number") { const runningScript = findRunningScriptByPid(commandArray[0], server); if (runningScript == null) { - terminal.error(`No script with pid ${commandArray[0]} is not running on the server`); + terminal.error(`No script with PID ${commandArray[0]} is running on the server`); return; } LogBoxEvents.emit(runningScript); From 6d79561859aea8a975eacb2f941f0ed4101655b5 Mon Sep 17 00:00:00 2001 From: Dan Date: Sun, 19 Dec 2021 04:03:14 +0000 Subject: [PATCH 6/9] fix(servers): fix issue of space in server name Replace the space in a server name with a hyphen (-), also noticed some interesting behaviour with the 'count up naming', so tweaked that. Resolves danielyxie/bitburner#1999 --- src/Server/ServerHelpers.ts | 11 +++++++---- src/Server/ServerPurchases.ts | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Server/ServerHelpers.ts b/src/Server/ServerHelpers.ts index 4f49f2338..affb42a00 100644 --- a/src/Server/ServerHelpers.ts +++ b/src/Server/ServerHelpers.ts @@ -16,22 +16,25 @@ import { isValidNumber } from "../utils/helpers/isValidNumber"; * does not have a duplicate hostname/ip. */ export function safetlyCreateUniqueServer(params: IConstructorParams): Server { + let hostname: string = params.hostname.replace(/ /g, `-`); + if (params.ip != null && ipExists(params.ip)) { params.ip = createUniqueRandomIp(); } - if (GetServer(params.hostname) != null) { + if (GetServer(hostname) != null) { + hostname = `${hostname}-0`; + // Use a for loop to ensure that we don't get suck in an infinite loop somehow - let hostname: string = params.hostname; for (let i = 0; i < 200; ++i) { - hostname = `${params.hostname}-${i}`; + hostname = hostname.replace(/-[0-9]+$/, `-${i}`); if (GetServer(hostname) == null) { break; } } - params.hostname = hostname; } + params.hostname = hostname; return new Server(params); } diff --git a/src/Server/ServerPurchases.ts b/src/Server/ServerPurchases.ts index 7d2b754e8..1c7f6d08d 100644 --- a/src/Server/ServerPurchases.ts +++ b/src/Server/ServerPurchases.ts @@ -96,7 +96,7 @@ export function purchaseServer(hostname: string, ram: number, cost: number, p: I p.loseMoney(cost, "servers"); - dialogBoxCreate("Server successfully purchased with hostname " + hostname); + dialogBoxCreate("Server successfully purchased with hostname " + newServ.hostname); } // Manually upgrade RAM on home computer (NOT through Netscript) From 1dcc17c4fb554a5c755ffe385c3c901d61f23ba3 Mon Sep 17 00:00:00 2001 From: MageKing17 Date: Sat, 18 Dec 2021 21:22:34 -0800 Subject: [PATCH 7/9] Update ls.tsx `args[numArgs - 1]` is the last argument in the list, so correct usage was being flagged as incorrect, and incorrect usage wasn't working anyway because the filter was `"undefined"`. Additionally, the function seemed confused as to whether or not `ls` counted as an argument (AFAICT, it isn't). Fixes #1994. --- src/Terminal/commands/ls.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Terminal/commands/ls.tsx b/src/Terminal/commands/ls.tsx index f964a86a6..5cc498308 100644 --- a/src/Terminal/commands/ls.tsx +++ b/src/Terminal/commands/ls.tsx @@ -17,7 +17,7 @@ export function ls( terminal.error("Incorrect usage of ls command. Usage: ls [dir] [| grep pattern]"); } - if (numArgs > 5 || numArgs === 3) { + if (numArgs > 4 || numArgs === 2) { return incorrectUsage(); } @@ -30,12 +30,12 @@ export function ls( prefix += "/"; } - // If there are 4+ arguments, then the last 3 must be for grep - if (numArgs >= 4) { - if (args[numArgs - 1] !== "grep" || args[numArgs - 2] !== "|") { + // If there are 3+ arguments, then the last 3 must be for grep + if (numArgs >= 3) { + if (args[numArgs - 2] !== "grep" || args[numArgs - 3] !== "|") { return incorrectUsage(); } - filter = args[numArgs] + ""; + filter = args[numArgs - 1] + ""; } // If the second argument is not a pipe, then it must be for listing a directory From bc7f94ddda14f22b1421d59d28810599f316782c Mon Sep 17 00:00:00 2001 From: hydroflame <79246165+hydroflame@users.noreply.github.com> Date: Sun, 19 Dec 2021 00:23:01 -0500 Subject: [PATCH 8/9] Update check.ts --- src/Terminal/commands/check.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Terminal/commands/check.ts b/src/Terminal/commands/check.ts index 6ec67ac6b..0bc198a2f 100644 --- a/src/Terminal/commands/check.ts +++ b/src/Terminal/commands/check.ts @@ -19,7 +19,7 @@ export function check( // Can only tail script files if (!isScriptFilename(scriptName)) { terminal.error( - `'check' can only be called on .script files (filename must end with ${validScriptExtensions.join(", ")})`, + `'check' can only be called on scripts files (filename must end with ${validScriptExtensions.join(", ")})`, ); return; } From 1ea8c62d4f6122d7ce8e5ad283c3da18ad2bc905 Mon Sep 17 00:00:00 2001 From: hydroflame <79246165+hydroflame@users.noreply.github.com> Date: Sun, 19 Dec 2021 00:23:10 -0500 Subject: [PATCH 9/9] Create check.ts