mirror of
https://github.com/microsoft/monaco-editor.git
synced 2025-12-22 17:25:39 +01:00
Merge branch 'main' into add-wgsl
This commit is contained in:
commit
6163a51770
14 changed files with 324 additions and 103 deletions
|
|
@ -1,5 +1,9 @@
|
|||
# Monaco Editor Changelog
|
||||
|
||||
## [0.37.1]
|
||||
|
||||
- Fixes Inline Completions feature
|
||||
|
||||
## [0.37.0]
|
||||
|
||||
- New `registerLinkOpener` API
|
||||
|
|
|
|||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "monaco-editor",
|
||||
"version": "0.37.0",
|
||||
"version": "0.37.1",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "monaco-editor",
|
||||
"version": "0.37.0",
|
||||
"version": "0.37.1",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "monaco-editor",
|
||||
"version": "0.37.0",
|
||||
"vscodeRef": "9eba21c20f8720575cbc6c531d60c042c554d465",
|
||||
"version": "0.37.1",
|
||||
"vscodeRef": "8f74fbfd1f2d8f6268a42df131726b218aafe511",
|
||||
"private": true,
|
||||
"description": "A browser based code editor",
|
||||
"homepage": "https://github.com/microsoft/monaco-editor",
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ import { exit } from "process";
|
|||
"yarn",
|
||||
[
|
||||
"tsc",
|
||||
"--target",
|
||||
"es6",
|
||||
"--noEmit",
|
||||
"--allowJs",
|
||||
"--checkJs",
|
||||
|
|
|
|||
|
|
@ -21,12 +21,24 @@ export interface IMonacoSetup {
|
|||
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(
|
||||
setup: IMonacoSetup = prodMonacoSetup
|
||||
): Promise<typeof monaco> {
|
||||
if (!loadMonacoPromise) {
|
||||
loadMonacoPromise = _loadMonaco(setup);
|
||||
if (!loading) {
|
||||
loading = true;
|
||||
_loadMonaco(setup).then(resolve, reject);
|
||||
}
|
||||
return loadMonacoPromise;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { loadMonaco } from "../monaco-loader";
|
||||
import { IMessage, IPreviewState } from "../shared";
|
||||
import { IMessageFromRunner, IMessageToRunner, IPreviewState } from "../shared";
|
||||
import "./style.scss";
|
||||
|
||||
window.addEventListener("message", (event) => {
|
||||
|
|
@ -14,7 +14,7 @@ window.addEventListener("message", (event) => {
|
|||
console.error("not in sandbox");
|
||||
return;
|
||||
}
|
||||
const e = event.data as IMessage | { kind: undefined };
|
||||
const e = event.data as IMessageToRunner | { kind: undefined };
|
||||
if (e.kind === "initialize") {
|
||||
initialize(e.state);
|
||||
} else if (e.kind === "update-css") {
|
||||
|
|
@ -51,8 +51,10 @@ async function initialize(state: IPreviewState) {
|
|||
|
||||
document.body.innerHTML += state.html;
|
||||
|
||||
const js = massageJs(state.js);
|
||||
|
||||
try {
|
||||
eval(state.js);
|
||||
eval(js);
|
||||
} catch (err) {
|
||||
const pre = document.createElement("pre");
|
||||
pre.appendChild(
|
||||
|
|
@ -61,3 +63,42 @@ async function initialize(state: IPreviewState) {
|
|||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { IMonacoSetup } from "./monaco-loader";
|
||||
|
||||
export type IMessage =
|
||||
export type IMessageToRunner =
|
||||
| {
|
||||
kind: "initialize";
|
||||
state: IPreviewState;
|
||||
|
|
@ -15,6 +15,16 @@ export type IMessage =
|
|||
css: string;
|
||||
};
|
||||
|
||||
export type IMessageFromRunner =
|
||||
| {
|
||||
kind: "update-code-string";
|
||||
codeStringName: string;
|
||||
value: string;
|
||||
}
|
||||
| {
|
||||
kind: "reload";
|
||||
};
|
||||
|
||||
export interface IPlaygroundProject {
|
||||
js: string;
|
||||
css: string;
|
||||
|
|
|
|||
|
|
@ -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({
|
||||
original: originalModel,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
const text = `function hello() {
|
||||
const value = /* set from `myEditor.getModel()`: */ `function hello() {
|
||||
alert('Hello world!');
|
||||
}`;
|
||||
|
||||
// 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",
|
||||
automaticLayout: true,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -11,10 +11,12 @@ customElements.define(
|
|||
const shadowRoot = this.attachShadow({ mode: "open" });
|
||||
|
||||
// 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 */ (
|
||||
document.getElementById("editor-template")
|
||||
|
|
|
|||
|
|
@ -12,7 +12,11 @@ import {
|
|||
reaction,
|
||||
runInAction,
|
||||
} from "mobx";
|
||||
import { IMonacoSetup, loadMonaco } from "../../../monaco-loader";
|
||||
import {
|
||||
IMonacoSetup,
|
||||
loadMonaco,
|
||||
waitForLoadedMonaco,
|
||||
} from "../../../monaco-loader";
|
||||
import { IPlaygroundProject, IPreviewState } from "../../../shared";
|
||||
import { monacoEditorVersion } from "../../monacoEditorVersion";
|
||||
import { Debouncer } from "../../utils/Debouncer";
|
||||
|
|
@ -56,12 +60,23 @@ export class PlaygroundModel {
|
|||
|
||||
public readonly serializer = new StateUrlSerializer(this);
|
||||
|
||||
reload(): void {
|
||||
public reload(): void {
|
||||
this.reloadKey++;
|
||||
}
|
||||
|
||||
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
|
||||
get monacoSetup(): IMonacoSetup {
|
||||
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() {
|
||||
let lastState = this.state;
|
||||
|
||||
this.dispose.track({
|
||||
dispose: reaction(
|
||||
() => ({ state: this.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) {
|
||||
handler.handlePreview(state);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (state.key !== lastState.key) {
|
||||
action(); // sync update
|
||||
} else {
|
||||
this.debouncer.run(action);
|
||||
}
|
||||
},
|
||||
{ name: "update preview" }
|
||||
),
|
||||
});
|
||||
|
||||
const observablePromise = new ObservablePromise(loadMonaco());
|
||||
const observablePromise = new ObservablePromise(waitForLoadedMonaco());
|
||||
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 =
|
||||
monaco.languages.typescript.javascriptDefaults.getCompilerOptions();
|
||||
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 {
|
||||
this.settingsDialogModel = new SettingsDialogModel(
|
||||
this.settings.settings
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import { PlaygroundModel } from "./PlaygroundModel";
|
|||
import { Preview } from "./Preview";
|
||||
import { SettingsDialog } from "./SettingsDialog";
|
||||
import { Button, Col, Row, Stack } from "../../components/bootstrap";
|
||||
import { ButtonGroup } from "react-bootstrap";
|
||||
import { ButtonGroup, FormCheck } from "react-bootstrap";
|
||||
|
||||
@hotComponent(module)
|
||||
@observer
|
||||
|
|
@ -37,88 +37,122 @@ export class PlaygroundPageContent extends React.Component<
|
|||
className="h-100 g-2"
|
||||
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>
|
||||
<LabeledEditor
|
||||
label="Preview"
|
||||
titleBarItems={
|
||||
<div
|
||||
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
|
||||
type="button"
|
||||
className="btn btn-light settings bi-arrow-clockwise"
|
||||
className={
|
||||
"btn settings bi-arrow-clockwise " +
|
||||
(model.isDirty
|
||||
? "btn-primary"
|
||||
: "btn-light")
|
||||
}
|
||||
style={{
|
||||
fontSize: 20,
|
||||
padding: "0px 4px",
|
||||
|
|
@ -414,7 +448,16 @@ class Editor extends React.Component<{
|
|||
() => {
|
||||
const value = this.props.value.get();
|
||||
if (!this.ignoreChange) {
|
||||
this.editor!.setValue(value);
|
||||
this.model.pushEditOperations(
|
||||
null,
|
||||
[
|
||||
{
|
||||
range: this.model.getFullModelRange(),
|
||||
text: value,
|
||||
},
|
||||
],
|
||||
() => null
|
||||
);
|
||||
}
|
||||
},
|
||||
{ name: "update text" }
|
||||
|
|
@ -424,6 +467,7 @@ class Editor extends React.Component<{
|
|||
|
||||
componentWillUnmount() {
|
||||
this.disposables.forEach((d) => d.dispose());
|
||||
this.model.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,11 @@ import * as React from "react";
|
|||
import { IPreviewHandler, PlaygroundModel } from "./PlaygroundModel";
|
||||
import { observer } from "mobx-react";
|
||||
import { observable } from "mobx";
|
||||
import { IMessage, IPreviewState } from "../../../shared";
|
||||
import {
|
||||
IMessageFromRunner,
|
||||
IMessageToRunner,
|
||||
IPreviewState,
|
||||
} from "../../../shared";
|
||||
|
||||
@observer
|
||||
export class Preview
|
||||
|
|
@ -40,7 +44,7 @@ export class Preview
|
|||
return;
|
||||
}
|
||||
|
||||
const message: IMessage = {
|
||||
const message: IMessageToRunner = {
|
||||
kind: "initialize",
|
||||
state: this.currentState,
|
||||
};
|
||||
|
|
@ -48,6 +52,17 @@ export class Preview
|
|||
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() {
|
||||
|
|
@ -68,7 +83,7 @@ export class Preview
|
|||
{
|
||||
kind: "update-css",
|
||||
css: state.css,
|
||||
} as IMessage,
|
||||
} as IMessageToRunner,
|
||||
{
|
||||
targetOrigin: "*",
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,14 @@ export class SettingsModel {
|
|||
this.setSettings({ ...this._settings, previewFullScreen: value });
|
||||
}
|
||||
|
||||
get autoReload() {
|
||||
return this._settings.autoReload ?? true;
|
||||
}
|
||||
|
||||
set autoReload(value: boolean) {
|
||||
this.setSettings({ ...this._settings, autoReload: value });
|
||||
}
|
||||
|
||||
constructor() {
|
||||
const settingsStr = localStorage.getItem(this.settingsKey);
|
||||
if (settingsStr) {
|
||||
|
|
@ -70,6 +78,7 @@ export interface Settings {
|
|||
customConfig: JsonString<IMonacoSetup>;
|
||||
|
||||
previewFullScreen: boolean;
|
||||
autoReload: boolean | undefined;
|
||||
}
|
||||
|
||||
export type JsonString<T> = string;
|
||||
|
|
@ -167,6 +176,7 @@ export function getDefaultSettings(): Settings {
|
|||
loaderPathsConfig: "",
|
||||
}),
|
||||
previewFullScreen: false,
|
||||
autoReload: true,
|
||||
};
|
||||
return defaultSettings;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue