monaco-editor/website/src/monaco-loader.ts

108 lines
3.0 KiB
TypeScript

/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export function getLoadedMonaco(): typeof monaco {
if (!monaco) {
throw new Error("monaco is not loaded yet");
}
return monaco;
}
export function getMonaco(): typeof monaco | undefined {
return (window as any).monaco;
}
export interface IMonacoSetup {
loaderUrl: string;
loaderConfigPaths: Record<string, string>;
codiconUrl: string;
monacoTypesUrl: string | 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 (!loading) {
loading = true;
_loadMonaco(setup).then(resolve, reject);
}
return loadMonacoPromise;
}
async function _loadMonaco(setup: IMonacoSetup): Promise<typeof monaco> {
const global = self as any;
if (!(global as any).require) {
await loadScript(setup.loaderUrl);
}
global.AMD = true;
global.getCodiconPath = () => {
return setup.codiconUrl;
};
/** @type {any} */
const req = global.require as any;
req.config({ paths: setup.loaderConfigPaths });
return new Promise((res) => {
// First load editor.main. If it inlines the plugins, we don't want to try to load them from the server.
req(["vs/editor/editor.main"], () => {
req(
[
"vs/basic-languages/monaco.contribution",
"vs/language/css/monaco.contribution",
"vs/language/html/monaco.contribution",
"vs/language/json/monaco.contribution",
"vs/language/typescript/monaco.contribution",
],
() => {
res(monaco);
}
);
});
});
}
function loadScript(path: string): Promise<void> {
return new Promise((res) => {
const script = document.createElement("script");
script.onload = () => res();
script.async = true;
script.type = "text/javascript";
script.src = path; // CodeQL [SM01507] This is safe because the runner (that allows for dynamic paths) runs in an isolated iframe. The hosting website uses a static path configuration. // CodeQL [SM03712] This is safe because the runner (that allows for dynamic paths) runs in an isolated iframe. The hosting website uses a static path configuration.
document.head.appendChild(script);
});
}
export const prodMonacoSetup = getMonacoSetup(
"node_modules/monaco-editor/min/vs"
);
export function getMonacoSetup(corePath: string): IMonacoSetup {
const loaderConfigPaths = {
vs: `${corePath}`,
};
return {
loaderUrl: `${corePath}/loader.js`,
loaderConfigPaths,
codiconUrl: `${corePath}/base/browser/ui/codicons/codicon/codicon.ttf`,
monacoTypesUrl: undefined,
};
}