Save data sanitization

- Run in `Editor.beforeMount`, as well as when the
options modal is closed
- Recursively validates all token colors and
replaces them with bright red if they're invalid
This commit is contained in:
nickofolas 2022-01-30 10:38:58 -06:00 committed by nickofolas
parent 739ca27ab9
commit d1edbe9a43
2 changed files with 48 additions and 9 deletions

@ -25,7 +25,7 @@ import { Settings } from "../../Settings/Settings";
import { iTutorialNextStep, ITutorial, iTutorialSteps } from "../../InteractiveTutorial";
import { debounce } from "lodash";
import { saveObject } from "../../SaveObject";
import { loadThemes, makeTheme } from "./themes";
import { loadThemes, makeTheme, sanitizeTheme } from "./themes";
import { GetServer } from "../../Server/AllServers";
import Button from "@mui/material/Button";
@ -362,6 +362,7 @@ export function Root(props: IProps): React.ReactElement {
monaco.languages.typescript.javascriptDefaults.addExtraLib(source, "netscript.d.ts");
monaco.languages.typescript.typescriptDefaults.addExtraLib(source, "netscript.d.ts");
loadThemes(monaco);
sanitizeTheme(Settings.EditorTheme);
monaco.editor.defineTheme("customTheme", makeTheme(Settings.EditorTheme));
}
@ -995,6 +996,7 @@ export function Root(props: IProps): React.ReactElement {
<OptionsModal
open={optionsOpen}
onClose={() => {
sanitizeTheme(Settings.EditorTheme);
monacoRef.current?.editor.defineTheme("customTheme", makeTheme(Settings.EditorTheme));
setOptionsOpen(false);
}}
@ -1006,6 +1008,7 @@ export function Root(props: IProps): React.ReactElement {
vim: Settings.MonacoVim,
}}
save={(options: Options) => {
sanitizeTheme(Settings.EditorTheme);
monacoRef.current?.editor.defineTheme("customTheme", makeTheme(Settings.EditorTheme));
setOptions(options);
Settings.MonacoTheme = options.theme;

@ -1,12 +1,15 @@
export interface IScriptEditorTheme {
[key: string]: any;
base: string;
inherit: boolean;
common: {
[key: string]: string;
accent: string;
bg: string;
fg: string;
};
syntax: {
[key: string]: string;
tag: string;
entity: string;
string: string;
@ -18,13 +21,16 @@ export interface IScriptEditorTheme {
error: string;
};
ui: {
[key: string]: any;
line: string;
panel: {
[key: string]: string;
bg: string;
selected: string;
border: string;
};
selection: {
[key: string]: string;
bg: string;
};
};
@ -34,20 +40,20 @@ export const defaultMonacoTheme: IScriptEditorTheme = {
base: "vs-dark",
inherit: true,
common: {
accent: "b5cea8",
accent: "B5CEA8",
bg: "1E1E1E",
fg: "D4D4D4",
},
syntax: {
tag: "569cd6",
entity: "569cd6",
string: "ce9178",
tag: "569CD6",
entity: "569CD6",
string: "CE9178",
regexp: "646695",
markup: "569cd6",
keyword: "569cd6",
markup: "569CD6",
keyword: "569CD6",
comment: "6A9955",
constant: "569cd6",
error: "f44747"
constant: "569CD6",
error: "F44747"
},
ui: {
line: "1E1E1E",
@ -62,6 +68,36 @@ export const defaultMonacoTheme: IScriptEditorTheme = {
}
}
// Regex used for token color validation
// https://github.com/microsoft/vscode/blob/973684056e67153952f495fce93bf50d0ec0b892/src/vs/editor/common/languages/supports/tokenization.ts#L153
const colorRegExp = /^#?([0-9A-Fa-f]{6})([0-9A-Fa-f]{2})?$/;
// Recursively sanitize the theme data to prevent errors
// Invalid data will be replaced with FF0000 (bright red)
export const sanitizeTheme = (theme: IScriptEditorTheme): void => {
for (const [k, v] of Object.entries(theme)) {
switch (k) {
case "base":
if (!["vs-dark", "vs"].includes(theme.base)) theme.base = "vs-dark";
continue;
case "inherit":
if (typeof theme.inherit !== "boolean") theme.inherit = true;
continue;
}
const repairBlock = (block: { [key: string]: any }): void => {
for (const [k, v] of Object.entries(block)) {
if (typeof v === "object") {
repairBlock(v as { [key: string]: string });
} else {
if (!v.match(colorRegExp)) block[k] = "FF0000";
}
}
}
repairBlock(v);
}
}
export function makeTheme(theme: IScriptEditorTheme): any {
const themeRules = [
{