Browse Source

Merge branch 'main' into add-wgsl

David Neto 2 years ago
parent
commit
6163a51770

+ 4 - 0
CHANGELOG.md

@@ -1,5 +1,9 @@
 # Monaco Editor Changelog
 # Monaco Editor Changelog
 
 
+## [0.37.1]
+
+- Fixes Inline Completions feature
+
 ## [0.37.0]
 ## [0.37.0]
 
 
 - New `registerLinkOpener` API
 - New `registerLinkOpener` API

+ 2 - 2
package-lock.json

@@ -1,12 +1,12 @@
 {
 {
 	"name": "monaco-editor",
 	"name": "monaco-editor",
-	"version": "0.37.0",
+	"version": "0.37.1",
 	"lockfileVersion": 2,
 	"lockfileVersion": 2,
 	"requires": true,
 	"requires": true,
 	"packages": {
 	"packages": {
 		"": {
 		"": {
 			"name": "monaco-editor",
 			"name": "monaco-editor",
-			"version": "0.37.0",
+			"version": "0.37.1",
 			"hasInstallScript": true,
 			"hasInstallScript": true,
 			"license": "MIT",
 			"license": "MIT",
 			"devDependencies": {
 			"devDependencies": {

+ 2 - 2
package.json

@@ -1,7 +1,7 @@
 {
 {
 	"name": "monaco-editor",
 	"name": "monaco-editor",
-	"version": "0.37.0",
-	"vscodeRef": "9eba21c20f8720575cbc6c531d60c042c554d465",
+	"version": "0.37.1",
+	"vscodeRef": "8f74fbfd1f2d8f6268a42df131726b218aafe511",
 	"private": true,
 	"private": true,
 	"description": "A browser based code editor",
 	"description": "A browser based code editor",
 	"homepage": "https://github.com/microsoft/monaco-editor",
 	"homepage": "https://github.com/microsoft/monaco-editor",

+ 2 - 0
website/scripts/check-playground-samples-js.ts

@@ -14,6 +14,8 @@ import { exit } from "process";
 					"yarn",
 					"yarn",
 					[
 					[
 						"tsc",
 						"tsc",
+						"--target",
+						"es6",
 						"--noEmit",
 						"--noEmit",
 						"--allowJs",
 						"--allowJs",
 						"--checkJs",
 						"--checkJs",

+ 15 - 3
website/src/monaco-loader.ts

@@ -21,12 +21,24 @@ export interface IMonacoSetup {
 	monacoTypesUrl: string | undefined;
 	monacoTypesUrl: string | undefined;
 }
 }
 
 
-let loadMonacoPromise: Promise<typeof monaco> | undefined;
+let loading = false;
+let resolve: (value: typeof monaco) => void;
+let reject: (error: unknown) => void;
+let loadMonacoPromise = new Promise<typeof monaco>((res, rej) => {
+	resolve = res;
+	reject = rej;
+});
+
+export async function waitForLoadedMonaco(): Promise<typeof monaco> {
+	return loadMonacoPromise;
+}
+
 export async function loadMonaco(
 export async function loadMonaco(
 	setup: IMonacoSetup = prodMonacoSetup
 	setup: IMonacoSetup = prodMonacoSetup
 ): Promise<typeof monaco> {
 ): Promise<typeof monaco> {
-	if (!loadMonacoPromise) {
-		loadMonacoPromise = _loadMonaco(setup);
+	if (!loading) {
+		loading = true;
+		_loadMonaco(setup).then(resolve, reject);
 	}
 	}
 	return loadMonacoPromise;
 	return loadMonacoPromise;
 }
 }

+ 44 - 3
website/src/runner/index.ts

@@ -4,7 +4,7 @@
  *--------------------------------------------------------------------------------------------*/
  *--------------------------------------------------------------------------------------------*/
 
 
 import { loadMonaco } from "../monaco-loader";
 import { loadMonaco } from "../monaco-loader";
-import { IMessage, IPreviewState } from "../shared";
+import { IMessageFromRunner, IMessageToRunner, IPreviewState } from "../shared";
 import "./style.scss";
 import "./style.scss";
 
 
 window.addEventListener("message", (event) => {
 window.addEventListener("message", (event) => {
@@ -14,7 +14,7 @@ window.addEventListener("message", (event) => {
 		console.error("not in sandbox");
 		console.error("not in sandbox");
 		return;
 		return;
 	}
 	}
-	const e = event.data as IMessage | { kind: undefined };
+	const e = event.data as IMessageToRunner | { kind: undefined };
 	if (e.kind === "initialize") {
 	if (e.kind === "initialize") {
 		initialize(e.state);
 		initialize(e.state);
 	} else if (e.kind === "update-css") {
 	} else if (e.kind === "update-css") {
@@ -51,8 +51,10 @@ async function initialize(state: IPreviewState) {
 
 
 	document.body.innerHTML += state.html;
 	document.body.innerHTML += state.html;
 
 
+	const js = massageJs(state.js);
+
 	try {
 	try {
-		eval(state.js);
+		eval(js);
 	} catch (err) {
 	} catch (err) {
 		const pre = document.createElement("pre");
 		const pre = document.createElement("pre");
 		pre.appendChild(
 		pre.appendChild(
@@ -61,3 +63,42 @@ async function initialize(state: IPreviewState) {
 		document.body.insertBefore(pre, document.body.firstChild);
 		document.body.insertBefore(pre, document.body.firstChild);
 	}
 	}
 }
 }
+
+function sendMessageToParent(message: IMessageFromRunner) {
+	window.parent.postMessage(message, "*");
+}
+
+(globalThis as any).$sendMessageToParent = sendMessageToParent;
+
+(globalThis as any).$bindModelToCodeStr = function bindModel(
+	model: any,
+	codeStringName: string
+) {
+	model.onDidChangeContent(() => {
+		const value = model.getValue();
+		sendMessageToParent({
+			kind: "update-code-string",
+			codeStringName,
+			value,
+		});
+	});
+};
+
+function massageJs(js: string) {
+	/*
+	Alternate experimental syntax: // bind to code string: `editor.getModel()` -> codeString
+
+	const bindToCodeStringRegexp = /\/\/ bind to code string: `(.*?)` -> (.*?)(\n|$)/g;
+	js = js.replaceAll(bindToCodeStringRegexp, (match, p1, p2) => {
+		return `globalThis.bindModelToCodeStr(${p1}, ${JSON.stringify(p2)})\n`;
+	});
+	*/
+
+	const setFromRegexp = /\/*\Wset from `(.*?)`:\W*\//g;
+	for (const m of js.matchAll(setFromRegexp)) {
+		const p1 = m[1];
+		const target = JSON.stringify("set from `" + p1 + "`");
+		js += `\n try { globalThis.$bindModelToCodeStr(${p1}, ${target}); } catch (e) { console.error(e); }`;
+	}
+	return js;
+}

+ 11 - 1
website/src/shared.ts

@@ -5,7 +5,7 @@
 
 
 import { IMonacoSetup } from "./monaco-loader";
 import { IMonacoSetup } from "./monaco-loader";
 
 
-export type IMessage =
+export type IMessageToRunner =
 	| {
 	| {
 			kind: "initialize";
 			kind: "initialize";
 			state: IPreviewState;
 			state: IPreviewState;
@@ -15,6 +15,16 @@ export type IMessage =
 			css: string;
 			css: string;
 	  };
 	  };
 
 
+export type IMessageFromRunner =
+	| {
+			kind: "update-code-string";
+			codeStringName: string;
+			value: string;
+	  }
+	| {
+			kind: "reload";
+	  };
+
 export interface IPlaygroundProject {
 export interface IPlaygroundProject {
 	js: string;
 	js: string;
 	css: string;
 	css: string;

+ 14 - 4
website/src/website/data/playground-samples/creating-the-diffeditor/hello-diff-world/sample.js

@@ -1,8 +1,18 @@
-var originalModel = monaco.editor.createModel("heLLo world!", "text/plain");
-var modifiedModel = monaco.editor.createModel("hello orlando!", "text/plain");
+const originalModel = monaco.editor.createModel(
+	/* set from `originalModel`: */ `hello world`,
+	"text/plain"
+);
+const modifiedModel = monaco.editor.createModel(
+	/* set from `modifiedModel`: */ `Hello World!`,
+	"text/plain"
+);
 
 
-var diffEditor = monaco.editor.createDiffEditor(
-	document.getElementById("container")
+const diffEditor = monaco.editor.createDiffEditor(
+	document.getElementById("container"),
+	{
+		originalEditable: true,
+		automaticLayout: true,
+	}
 );
 );
 diffEditor.setModel({
 diffEditor.setModel({
 	original: originalModel,
 	original: originalModel,

+ 3 - 3
website/src/website/data/playground-samples/creating-the-editor/hello-world/sample.js

@@ -1,10 +1,10 @@
-const text = `function hello() {
+const value = /* set from `myEditor.getModel()`: */ `function hello() {
 	alert('Hello world!');
 	alert('Hello world!');
 }`;
 }`;
 
 
 // Hover on each property to see its docs!
 // Hover on each property to see its docs!
-monaco.editor.create(document.getElementById("container"), {
-	value: text,
+const myEditor = monaco.editor.create(document.getElementById("container"), {
+	value,
 	language: "javascript",
 	language: "javascript",
 	automaticLayout: true,
 	automaticLayout: true,
 });
 });

+ 5 - 3
website/src/website/data/playground-samples/creating-the-editor/web-component/sample.js

@@ -11,10 +11,12 @@ customElements.define(
 			const shadowRoot = this.attachShadow({ mode: "open" });
 			const shadowRoot = this.attachShadow({ mode: "open" });
 
 
 			// Copy over editor styles
 			// Copy over editor styles
-			const style = document.querySelector(
-				"link[rel='stylesheet'][data-name='vs/editor/editor.main']"
+			const styles = document.querySelectorAll(
+				"link[rel='stylesheet'][data-name^='vs/']"
 			);
 			);
-			shadowRoot.appendChild(style.cloneNode(true));
+			for (const style of styles) {
+				shadowRoot.appendChild(style.cloneNode(true));
+			}
 
 
 			const template = /** @type HTMLTemplateElement */ (
 			const template = /** @type HTMLTemplateElement */ (
 				document.getElementById("editor-template")
 				document.getElementById("editor-template")

+ 78 - 7
website/src/website/pages/playground/PlaygroundModel.ts

@@ -12,7 +12,11 @@ import {
 	reaction,
 	reaction,
 	runInAction,
 	runInAction,
 } from "mobx";
 } from "mobx";
-import { IMonacoSetup, loadMonaco } from "../../../monaco-loader";
+import {
+	IMonacoSetup,
+	loadMonaco,
+	waitForLoadedMonaco,
+} from "../../../monaco-loader";
 import { IPlaygroundProject, IPreviewState } from "../../../shared";
 import { IPlaygroundProject, IPreviewState } from "../../../shared";
 import { monacoEditorVersion } from "../../monacoEditorVersion";
 import { monacoEditorVersion } from "../../monacoEditorVersion";
 import { Debouncer } from "../../utils/Debouncer";
 import { Debouncer } from "../../utils/Debouncer";
@@ -56,12 +60,23 @@ export class PlaygroundModel {
 
 
 	public readonly serializer = new StateUrlSerializer(this);
 	public readonly serializer = new StateUrlSerializer(this);
 
 
-	reload(): void {
+	public reload(): void {
 		this.reloadKey++;
 		this.reloadKey++;
 	}
 	}
 
 
 	private readonly _previewHandlers = new Set<IPreviewHandler>();
 	private readonly _previewHandlers = new Set<IPreviewHandler>();
 
 
+	private _wasEverNonFullScreen = false;
+	public get wasEverNonFullScreen() {
+		if (this._wasEverNonFullScreen) {
+			return true;
+		}
+		if (!this.settings.previewFullScreen) {
+			this._wasEverNonFullScreen = true;
+		}
+		return this._wasEverNonFullScreen;
+	}
+
 	@computed.struct
 	@computed.struct
 	get monacoSetup(): IMonacoSetup {
 	get monacoSetup(): IMonacoSetup {
 		const sourceOverride = this.serializer.sourceOverride;
 		const sourceOverride = this.serializer.sourceOverride;
@@ -125,27 +140,61 @@ export class PlaygroundModel {
 		}
 		}
 	}
 	}
 
 
-	private readonly debouncer = new Debouncer(250);
+	private readonly debouncer = new Debouncer(700);
+
+	@observable
+	public isDirty = false;
 
 
 	constructor() {
 	constructor() {
+		let lastState = this.state;
+
 		this.dispose.track({
 		this.dispose.track({
 			dispose: reaction(
 			dispose: reaction(
 				() => ({ state: this.state }),
 				() => ({ state: this.state }),
 				({ state }) => {
 				({ state }) => {
-					this.debouncer.run(() => {
+					if (!this.settings.autoReload) {
+						if (
+							JSON.stringify(state.monacoSetup) ===
+								JSON.stringify(lastState.monacoSetup) &&
+							state.key === lastState.key
+						) {
+							this.isDirty = true;
+							return;
+						}
+					}
+					const action = () => {
+						this.isDirty = false;
+						lastState = state;
 						for (const handler of this._previewHandlers) {
 						for (const handler of this._previewHandlers) {
 							handler.handlePreview(state);
 							handler.handlePreview(state);
 						}
 						}
-					});
+					};
+
+					if (state.key !== lastState.key) {
+						action(); // sync update
+					} else {
+						this.debouncer.run(action);
+					}
 				},
 				},
 				{ name: "update preview" }
 				{ name: "update preview" }
 			),
 			),
 		});
 		});
 
 
-		const observablePromise = new ObservablePromise(loadMonaco());
+		const observablePromise = new ObservablePromise(waitForLoadedMonaco());
 		let disposable: Disposable | undefined = undefined;
 		let disposable: Disposable | undefined = undefined;
 
 
-		loadMonaco().then((m) => {
+		waitForLoadedMonaco().then((m) => {
+			this.dispose.track(
+				monaco.editor.addEditorAction({
+					id: "reload",
+					label: "Reload",
+					run: (editor, ...args) => {
+						this.reload();
+					},
+					keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter],
+				})
+			);
+
 			const options =
 			const options =
 				monaco.languages.typescript.javascriptDefaults.getCompilerOptions();
 				monaco.languages.typescript.javascriptDefaults.getCompilerOptions();
 			monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions(
 			monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions(
@@ -190,6 +239,28 @@ export class PlaygroundModel {
 		});
 		});
 	}
 	}
 
 
+	setCodeString(codeStringName: string, value: string) {
+		function escapeRegexpChars(str: string) {
+			return str.replace(/[-[\]/{}()*+?.\\^$|]/g, "\\$&");
+		}
+
+		const regexp = new RegExp(
+			"(\\b" +
+				escapeRegexpChars(codeStringName) +
+				":[^\\w`]*`)([^`\\\\]|\\n|\\\\\\\\|\\\\`)*`"
+		);
+		const js = this.js;
+		const str = value
+			.replaceAll("\\", "\\\\")
+			.replaceAll("$", "\\$")
+			.replaceAll("`", "\\`");
+		const newJs = js.replace(regexp, "$1" + str + "`");
+		const autoReload = this.settings.autoReload;
+		this.settings.autoReload = false;
+		this.js = newJs;
+		this.settings.autoReload = autoReload;
+	}
+
 	public showSettingsDialog(): void {
 	public showSettingsDialog(): void {
 		this.settingsDialogModel = new SettingsDialogModel(
 		this.settingsDialogModel = new SettingsDialogModel(
 			this.settings.settings
 			this.settings.settings

+ 116 - 72
website/src/website/pages/playground/PlaygroundPageContent.tsx

@@ -18,7 +18,7 @@ import { PlaygroundModel } from "./PlaygroundModel";
 import { Preview } from "./Preview";
 import { Preview } from "./Preview";
 import { SettingsDialog } from "./SettingsDialog";
 import { SettingsDialog } from "./SettingsDialog";
 import { Button, Col, Row, Stack } from "../../components/bootstrap";
 import { Button, Col, Row, Stack } from "../../components/bootstrap";
-import { ButtonGroup } from "react-bootstrap";
+import { ButtonGroup, FormCheck } from "react-bootstrap";
 
 
 @hotComponent(module)
 @hotComponent(module)
 @observer
 @observer
@@ -37,88 +37,122 @@ export class PlaygroundPageContent extends React.Component<
 						className="h-100 g-2"
 						className="h-100 g-2"
 						style={{ flexWrap: "wrap-reverse" }}
 						style={{ flexWrap: "wrap-reverse" }}
 					>
 					>
-						<Col
-							md
-							className={
-								model.settings.previewFullScreen ? "d-none" : ""
-							}
-						>
-							<Vertical>
-								<div style={{ flex: 1 }}>
-									<LabeledEditor
-										label="JavaScript"
-										titleBarItems={
-											<div
-												className="hstack"
-												style={{ marginLeft: "auto" }}
-											>
-												<span
-													style={{ marginRight: 8 }}
+						{model.wasEverNonFullScreen && (
+							<Col
+								md
+								className={
+									model.settings.previewFullScreen
+										? "d-none"
+										: ""
+								}
+							>
+								<Vertical>
+									<div style={{ flex: 1 }}>
+										<LabeledEditor
+											label="JavaScript"
+											titleBarItems={
+												<div
+													className="hstack"
+													style={{
+														marginLeft: "auto",
+													}}
 												>
 												>
-													Example:
-												</span>
-												<Select<PlaygroundExample>
-													values={getPlaygroundExamples().map(
-														(e) => ({
-															groupTitle:
-																e.chapterTitle,
-															items: e.examples,
-														})
-													)}
-													value={ref(
-														model,
-														"selectedExample"
-													)}
-													getLabel={(i) => i.title}
-												/>
-											</div>
-										}
-									>
-										<Editor
-											language={"javascript"}
-											value={ref(model, "js")}
-										/>
-									</LabeledEditor>
-								</div>
+													<span
+														style={{
+															marginRight: 8,
+														}}
+													>
+														Example:
+													</span>
+													<Select<PlaygroundExample>
+														values={getPlaygroundExamples().map(
+															(e) => ({
+																groupTitle:
+																	e.chapterTitle,
+																items: e.examples,
+															})
+														)}
+														value={ref(
+															model,
+															"selectedExample"
+														)}
+														getLabel={(i) =>
+															i.title
+														}
+													/>
+												</div>
+											}
+										>
+											<Editor
+												language={"javascript"}
+												value={ref(model, "js")}
+											/>
+										</LabeledEditor>
+									</div>
 
 
-								<div>
-									<LabeledEditor label="HTML">
-										<Editor
-											height={{
-												kind: "dynamic",
-												maxHeight: 200,
-											}}
-											language={"html"}
-											value={ref(model, "html")}
-										/>
-									</LabeledEditor>
-								</div>
+									<div>
+										<LabeledEditor label="HTML">
+											<Editor
+												height={{
+													kind: "dynamic",
+													maxHeight: 200,
+												}}
+												language={"html"}
+												value={ref(model, "html")}
+											/>
+										</LabeledEditor>
+									</div>
 
 
-								<div>
-									<LabeledEditor label="CSS">
-										<Editor
-											height={{
-												kind: "dynamic",
-												maxHeight: 200,
-											}}
-											language={"css"}
-											value={ref(model, "css")}
-										/>
-									</LabeledEditor>
-								</div>
-							</Vertical>
-						</Col>
+									<div>
+										<LabeledEditor label="CSS">
+											<Editor
+												height={{
+													kind: "dynamic",
+													maxHeight: 200,
+												}}
+												language={"css"}
+												value={ref(model, "css")}
+											/>
+										</LabeledEditor>
+									</div>
+								</Vertical>
+							</Col>
+						)}
 						<Col md>
 						<Col md>
 							<LabeledEditor
 							<LabeledEditor
 								label="Preview"
 								label="Preview"
 								titleBarItems={
 								titleBarItems={
 									<div
 									<div
 										style={{ marginLeft: "auto" }}
 										style={{ marginLeft: "auto" }}
-										className="d-flex gap-2"
+										className="d-flex gap-2 align-items-center"
 									>
 									>
+										{model.settings.previewFullScreen || (
+											<FormCheck
+												label="Auto-Reload"
+												className="text-nowrap"
+												checked={
+													model.settings.autoReload
+												}
+												onChange={(e) => {
+													model.settings.autoReload =
+														e.target.checked;
+													if (
+														e.target.checked &&
+														model.isDirty
+													) {
+														model.reload();
+													}
+												}}
+											/>
+										)}
 										<Button
 										<Button
 											type="button"
 											type="button"
-											className="btn btn-light settings bi-arrow-clockwise"
+											className={
+												"btn settings bi-arrow-clockwise " +
+												(model.isDirty
+													? "btn-primary"
+													: "btn-light")
+											}
 											style={{
 											style={{
 												fontSize: 20,
 												fontSize: 20,
 												padding: "0px 4px",
 												padding: "0px 4px",
@@ -414,7 +448,16 @@ class Editor extends React.Component<{
 				() => {
 				() => {
 					const value = this.props.value.get();
 					const value = this.props.value.get();
 					if (!this.ignoreChange) {
 					if (!this.ignoreChange) {
-						this.editor!.setValue(value);
+						this.model.pushEditOperations(
+							null,
+							[
+								{
+									range: this.model.getFullModelRange(),
+									text: value,
+								},
+							],
+							() => null
+						);
 					}
 					}
 				},
 				},
 				{ name: "update text" }
 				{ name: "update text" }
@@ -424,6 +467,7 @@ class Editor extends React.Component<{
 
 
 	componentWillUnmount() {
 	componentWillUnmount() {
 		this.disposables.forEach((d) => d.dispose());
 		this.disposables.forEach((d) => d.dispose());
+		this.model.dispose();
 	}
 	}
 }
 }
 
 

+ 18 - 3
website/src/website/pages/playground/Preview.tsx

@@ -2,7 +2,11 @@ import * as React from "react";
 import { IPreviewHandler, PlaygroundModel } from "./PlaygroundModel";
 import { IPreviewHandler, PlaygroundModel } from "./PlaygroundModel";
 import { observer } from "mobx-react";
 import { observer } from "mobx-react";
 import { observable } from "mobx";
 import { observable } from "mobx";
-import { IMessage, IPreviewState } from "../../../shared";
+import {
+	IMessageFromRunner,
+	IMessageToRunner,
+	IPreviewState,
+} from "../../../shared";
 
 
 @observer
 @observer
 export class Preview
 export class Preview
@@ -40,7 +44,7 @@ export class Preview
 				return;
 				return;
 			}
 			}
 
 
-			const message: IMessage = {
+			const message: IMessageToRunner = {
 				kind: "initialize",
 				kind: "initialize",
 				state: this.currentState,
 				state: this.currentState,
 			};
 			};
@@ -48,6 +52,17 @@ export class Preview
 				targetOrigin: "*",
 				targetOrigin: "*",
 			});
 			});
 		});
 		});
+		window.addEventListener("message", (e) => {
+			if (e.source !== iframe.contentWindow) {
+				return;
+			}
+			const data = e.data as IMessageFromRunner;
+			if (data.kind === "update-code-string") {
+				this.props.model.setCodeString(data.codeStringName, data.value);
+			} else if (data.kind === "reload") {
+				this.props.model.reload();
+			}
+		});
 	};
 	};
 
 
 	componentDidMount() {
 	componentDidMount() {
@@ -68,7 +83,7 @@ export class Preview
 				{
 				{
 					kind: "update-css",
 					kind: "update-css",
 					css: state.css,
 					css: state.css,
-				} as IMessage,
+				} as IMessageToRunner,
 				{
 				{
 					targetOrigin: "*",
 					targetOrigin: "*",
 				}
 				}

+ 10 - 0
website/src/website/pages/playground/SettingsModel.ts

@@ -33,6 +33,14 @@ export class SettingsModel {
 		this.setSettings({ ...this._settings, previewFullScreen: value });
 		this.setSettings({ ...this._settings, previewFullScreen: value });
 	}
 	}
 
 
+	get autoReload() {
+		return this._settings.autoReload ?? true;
+	}
+
+	set autoReload(value: boolean) {
+		this.setSettings({ ...this._settings, autoReload: value });
+	}
+
 	constructor() {
 	constructor() {
 		const settingsStr = localStorage.getItem(this.settingsKey);
 		const settingsStr = localStorage.getItem(this.settingsKey);
 		if (settingsStr) {
 		if (settingsStr) {
@@ -70,6 +78,7 @@ export interface Settings {
 	customConfig: JsonString<IMonacoSetup>;
 	customConfig: JsonString<IMonacoSetup>;
 
 
 	previewFullScreen: boolean;
 	previewFullScreen: boolean;
+	autoReload: boolean | undefined;
 }
 }
 
 
 export type JsonString<T> = string;
 export type JsonString<T> = string;
@@ -167,6 +176,7 @@ export function getDefaultSettings(): Settings {
 			loaderPathsConfig: "",
 			loaderPathsConfig: "",
 		}),
 		}),
 		previewFullScreen: false,
 		previewFullScreen: false,
+		autoReload: true,
 	};
 	};
 	return defaultSettings;
 	return defaultSettings;
 }
 }