ngx-monaco-editor
ngx-monaco-editor copied to clipboard
Electron Support ?
The Editor is working fine in Web. But running it in Electron the Editor is not loading and I get the error:
window.require.config is not a function
It is from here:
var onGotAmdLoader = function () {
// Load monaco
window.require.config({ paths: { 'vs': baseUrl + "/monaco/vs" } });
window.require(['vs/editor/editor.main'], function () {
if (typeof _this.config.onMonacoLoad === 'function') {
_this.config.onMonacoLoad();
}
_this.initMonaco(_this.options);
resolve();
});
};
Currently this doesn't support Electron. You can work on that and raise a PR to dev branch.
..how can something not support Electron?
Same Issue here
Here's a sample, please fix https://github.com/Microsoft/monaco-editor-samples/blob/master/electron-amd/electron-index.html
I managed to make Monaco-Editor run in Electron. What I did is overwrite the ngAfterViewInit method from base-editor class generated in JavaScript with my additional implementation. I do this in my component class. Here is the code, hope it helps others (MAYBE SOMEONE CAN IMPLEMENT THIS AND CREATE A PULL REQUEST):
import { remote } from 'electron';
import { BaseEditor } from 'ngx-monaco-editor/base-editor';
import { BehaviorSubject } from 'rxjs';
import { KeyCode } from '../controls/ngx-datepicker/enums/key-code.enum';
import { ClarionEditorService } from './clarion-editor.service';
let loadedMonaco = false; // need this for electron
let loadPromise: Promise<void>; // need this for electron
// this function overwrites the internal function of ngx-monaco-editor
// and it is used just so that monaco editor can run in electron
BaseEditor.prototype.ngAfterViewInit = function() {
// tslint:disable-next-line:no-invalid-this
const _this = this;
if (loadedMonaco) {
// Wait until monaco editor is available
loadPromise.then(() => {
_this.initMonaco(_this.options);
});
} else {
loadedMonaco = true;
loadPromise = new Promise<void>((resolve: any) => {
const baseUrl: string = _this.config.baseUrl || '/assets';
if (typeof ((<any>window).monaco) === 'object') {
resolve();
return;
}
const onGotAmdLoader: any = () => {
// Load monaco
(<any>window).require.config({ paths: { vs: `${baseUrl}/monaco/vs` } });
(<any>window).require(['vs/editor/editor.main'], () => {
if (typeof _this.config.onMonacoLoad === 'function') {
_this.config.onMonacoLoad();
}
_this.initMonaco(_this.options);
resolve();
});
};
// Load AMD loader if necessary
if (!(<any>window).require) {
const loaderScript: HTMLScriptElement = document.createElement('script');
loaderScript.type = 'text/javascript';
loaderScript.src = `${baseUrl}/monaco/vs/loader.js`;
loaderScript.addEventListener('load', onGotAmdLoader);
document.body.appendChild(loaderScript);
} else if (!(<any>window).require.config) {
const amdLoader = (<any>window).require(`${baseUrl}/monaco/vs/loader.js`);
const amdRequire = amdLoader.require;
const monacoDir: string = remote.getGlobal('monacoDir');
// Load monaco
const mncDir = monacoDir.replace(/\\/g, '/');
amdRequire.config({ paths: { vs: mncDir } });
console.log('BaseEditor.prototype.ngAfterViewInit -> monacoDir', mncDir);
amdRequire(['vs/editor/editor.main'], () => {
if (typeof _this.config.onMonacoLoad === 'function') {
_this.config.onMonacoLoad();
}
_this.initMonaco(_this.options);
resolve();
});
} else {
onGotAmdLoader();
}
});
}
};
@Component({
selector: 'clarion-editor',
templateUrl: 'clarion-editor.component.html',
styleUrls: ['clarion-editor.component.scss'],
})
export class ClarionEditorComponent implements OnChanges, OnDestroy {
@Input() public text = new BehaviorSubject<string>('');
@Input() public variables: ContextVariable[] = [];
// @Input() public functions: any[];
@Output() public onLoaded = new EventEmitter();
// @Output() cursorPosition = new EventEmitter<monaco.editor.ICursorSelectionChangedEvent>();
// public clarionEditor: monaco.editor.ICodeEditor;
public editorOptions = <monaco.editor.IEditorOptions>{
wordWrap: 'on',
lineNumbersMinChars: 1,
scrollBeyondLastLine: false,
renderLineHighlight: 'none',
minimap: { enabled: false },
scrollbar: true,
language: 'clarionLanguage',
theme: 'clarionTheme',
mouseWheelZoom: true,
fontSize: 16,
automaticLayout: true,
folding: false,
// renderControlCharacters: true,
// renderWhitespace: 'all',
// formatOnPaste: true,
// formatOnType: true,
};
public monacoEditor: monaco.editor.IStandaloneCodeEditor;
constructor(private readonly editorService: ClarionEditorService) { }
public onEditorInit(editor: monaco.editor.IStandaloneCodeEditor) {
this.monacoEditor = editor;
//... ... ... ... irrelevant code
In my main.electron.js I defined the monacoDir variable:
global.monacoDir = `file:///${__dirname}/dist/assets/monaco/vs`;
A variation of the above solution worked for me.
One thing that's worth noting is that you can actual get around having to define a global monacoDir variable by using app.getAppPath() from remote.
const monacoDir = `${require('remote').app.getAppPath()}/dist/${baseUrl}`;
That being said, in development you will get an error complaining that you're not allowed to load a local resource editor.main.css
if you do it this way. You can get around this by adding webSecurity: false when creating the browser window in development
win = new BrowserWindow({
x: 0,
y: 0,
width: size.width,
height: size.height,
webPreferences: {
webSecurity: (development) ? false : true,
},
});
I found this: https://github.com/materiahq/ngx-monaco-editor and it works out of the box with https://github.com/maximegris/angular-electron.git.
@jakehockey10 But it seems to use and old version of angular and monaco, right?
@zerocewl The editor version may not be latest, but I it seems I'm using latest Angular
I confer with jakehockey10; angular8, bootsrap 4 and electron 8 - the https://github.com/materiahq/ngx-monaco-editor fork works perfectly in electron
The easy way is set nodeIntegration as false.
The second way is rename require(from Electron) to nodeRequire.
Then use nodeRequire to get Electron-related modules