mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
integrate monaco
- refactors createEditor out to own code files - moves ace editor to own code file - adds monaco editor to own code file - add monaco bootstrap - update mst to include monaco asset - update grunt to include new files and integrate
This commit is contained in:
parent
bded5490d2
commit
58da87898e
20
Gruntfile.js
20
Gruntfile.js
@ -181,6 +181,7 @@ module.exports = function(grunt) {
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/palette-editor.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/editor.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/editors/*.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/editors/code-editors/*.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/event-log.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/tray.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.js",
|
||||
@ -285,7 +286,9 @@ module.exports = function(grunt) {
|
||||
"packages/node_modules/@node-red/editor-client/public/index.html",
|
||||
"packages/node_modules/@node-red/editor-client/public/favicon.ico",
|
||||
"packages/node_modules/@node-red/editor-client/public/icons",
|
||||
"packages/node_modules/@node-red/editor-client/public/vendor"
|
||||
"packages/node_modules/@node-red/editor-client/public/vendor",
|
||||
"packages/node_modules/@node-red/editor-client/public/types/node",
|
||||
"packages/node_modules/@node-red/editor-client/public/types/node-red",
|
||||
]
|
||||
},
|
||||
release: {
|
||||
@ -375,11 +378,24 @@ module.exports = function(grunt) {
|
||||
src: [
|
||||
'ace/**',
|
||||
'jquery/css/base/**',
|
||||
'font-awesome/**'
|
||||
'font-awesome/**',
|
||||
'monaco/dist/**',
|
||||
'monaco/types/extraLibs.js',
|
||||
'monaco/style.css',
|
||||
'monaco/monaco-bootstrap.js'
|
||||
],
|
||||
expand: true,
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/vendor/'
|
||||
},
|
||||
{
|
||||
cwd: 'packages/node_modules/@node-red/editor-client/src',
|
||||
src: [
|
||||
'types/node/*.ts',
|
||||
'types/node-red/*.ts',
|
||||
],
|
||||
expand: true,
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/'
|
||||
},
|
||||
{
|
||||
cwd: 'packages/node_modules/@node-red/editor-client/src/icons',
|
||||
src: '**',
|
||||
|
@ -1525,6 +1525,7 @@ var buildingEditDialog = false;
|
||||
console.log("oneditresize",editing_node.id,editing_node.type,err.toString());
|
||||
}
|
||||
}
|
||||
if (nodeInfoEditor) {nodeInfoEditor.resize();} //markdown editor doesnt size up without this - idkw!?
|
||||
},
|
||||
open: function(tray, done) {
|
||||
if (editing_node.hasOwnProperty('outputs')) {
|
||||
@ -2759,94 +2760,7 @@ var buildingEditDialog = false;
|
||||
}
|
||||
}
|
||||
|
||||
function createEditor(options) {
|
||||
var el = options.element || $("#"+options.id)[0];
|
||||
var toolbarRow = $("<div>").appendTo(el);
|
||||
el = $("<div>").appendTo(el).addClass("red-ui-editor-text-container")[0];
|
||||
var editor = ace.edit(el);
|
||||
editor.setTheme("ace/theme/tomorrow");
|
||||
var session = editor.getSession();
|
||||
session.on("changeAnnotation", function () {
|
||||
var annotations = session.getAnnotations() || [];
|
||||
var i = annotations.length;
|
||||
var len = annotations.length;
|
||||
while (i--) {
|
||||
if (/doctype first\. Expected/.test(annotations[i].text)) { annotations.splice(i, 1); }
|
||||
else if (/Unexpected End of file\. Expected/.test(annotations[i].text)) { annotations.splice(i, 1); }
|
||||
}
|
||||
if (len > annotations.length) { session.setAnnotations(annotations); }
|
||||
});
|
||||
if (options.mode) {
|
||||
session.setMode(options.mode);
|
||||
}
|
||||
if (options.foldStyle) {
|
||||
session.setFoldStyle(options.foldStyle);
|
||||
} else {
|
||||
session.setFoldStyle('markbeginend');
|
||||
}
|
||||
if (options.options) {
|
||||
editor.setOptions(options.options);
|
||||
} else {
|
||||
editor.setOptions({
|
||||
enableBasicAutocompletion:true,
|
||||
enableSnippets:true,
|
||||
tooltipFollowsMouse: false
|
||||
});
|
||||
}
|
||||
if (options.readOnly) {
|
||||
editor.setOption('readOnly',options.readOnly);
|
||||
editor.container.classList.add("ace_read-only");
|
||||
}
|
||||
if (options.hasOwnProperty('lineNumbers')) {
|
||||
editor.renderer.setOption('showGutter',options.lineNumbers);
|
||||
}
|
||||
editor.$blockScrolling = Infinity;
|
||||
if (options.value) {
|
||||
session.setValue(options.value,-1);
|
||||
}
|
||||
if (options.globals) {
|
||||
setTimeout(function() {
|
||||
if (!!session.$worker) {
|
||||
session.$worker.send("setOptions", [{globals: options.globals, maxerr:1000}]);
|
||||
}
|
||||
},100);
|
||||
}
|
||||
if (options.mode === 'ace/mode/markdown') {
|
||||
$(el).addClass("red-ui-editor-text-container-toolbar");
|
||||
editor.toolbar = customEditTypes['_markdown'].buildToolbar(toolbarRow,editor);
|
||||
if (options.expandable !== false) {
|
||||
var expandButton = $('<button type="button" class="red-ui-button" style="float: right;"><i class="fa fa-expand"></i></button>').appendTo(editor.toolbar);
|
||||
RED.popover.tooltip(expandButton, RED._("markdownEditor.expand"));
|
||||
expandButton.on("click", function(e) {
|
||||
e.preventDefault();
|
||||
var value = editor.getValue();
|
||||
RED.editor.editMarkdown({
|
||||
value: value,
|
||||
width: "Infinity",
|
||||
cursor: editor.getCursorPosition(),
|
||||
complete: function(v,cursor) {
|
||||
editor.setValue(v, -1);
|
||||
editor.gotoLine(cursor.row+1,cursor.column,false);
|
||||
setTimeout(function() {
|
||||
editor.focus();
|
||||
},300);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
var helpButton = $('<button type="button" class="red-ui-editor-text-help red-ui-button red-ui-button-small"><i class="fa fa-question"></i></button>').appendTo($(el).parent());
|
||||
RED.popover.create({
|
||||
target: helpButton,
|
||||
trigger: 'click',
|
||||
size: "small",
|
||||
direction: "left",
|
||||
content: RED._("markdownEditor.format"),
|
||||
autoClose: 50
|
||||
});
|
||||
session.setUseWrapMode(true);
|
||||
}
|
||||
return editor;
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
@ -2862,6 +2776,8 @@ var buildingEditDialog = false;
|
||||
$("#node-dialog-cancel").trigger("click");
|
||||
$("#node-config-dialog-cancel").trigger("click");
|
||||
});
|
||||
//console.log("packages/node_modules/@node-red/editor-client/src/js/ui/editor.js ? init()") //TODO: Remove
|
||||
RED.editor.codeEditor.init();
|
||||
},
|
||||
edit: showEditDialog,
|
||||
editConfig: showEditConfigNodeDialog,
|
||||
@ -2908,9 +2824,14 @@ var buildingEditDialog = false;
|
||||
/**
|
||||
* Create a editor ui component
|
||||
* @param {object} options - the editor options
|
||||
* @function
|
||||
* @returs The code editor
|
||||
* @memberof RED.editor
|
||||
*/
|
||||
createEditor: createEditor
|
||||
createEditor: function(options) {
|
||||
return RED.editor.codeEditor.create(options);
|
||||
},
|
||||
get customEditTypes() {
|
||||
return customEditTypes;
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
107
packages/node_modules/@node-red/editor-client/src/js/ui/editors/code-editor.js
vendored
Normal file
107
packages/node_modules/@node-red/editor-client/src/js/ui/editors/code-editor.js
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
/**
|
||||
* @namespace RED.editor.codeEditor
|
||||
*/
|
||||
RED.editor.codeEditor = (function() {
|
||||
|
||||
const MONACO = "monaco";
|
||||
const ACE = "ace";
|
||||
const defaultEditor = ACE;
|
||||
const DEFAULT_SETTINGS = { lib: defaultEditor, options: {} };
|
||||
var selectedCodeEditor = null;
|
||||
var initialised = false;
|
||||
|
||||
function init() {
|
||||
var codeEditorSettings = RED.editor.codeEditor.settings;
|
||||
var editorChoice = codeEditorSettings.lib === MONACO ? MONACO : ACE;
|
||||
try {
|
||||
var browser = RED.utils.getBrowserInfo();
|
||||
selectedCodeEditor = RED.editor.codeEditor[editorChoice];
|
||||
//fall back to default code editor if there are any issues
|
||||
if (!selectedCodeEditor || (editorChoice === MONACO && (browser.ie || !window.monaco))) {
|
||||
selectedCodeEditor = RED.editor.codeEditor[defaultEditor];
|
||||
}
|
||||
initialised = selectedCodeEditor.init();
|
||||
} catch (error) {
|
||||
selectedCodeEditor = null;
|
||||
console.warn("Problem initialising '" + editorChoice + "' code editor", error);
|
||||
}
|
||||
if(!initialised) {
|
||||
selectedCodeEditor = RED.editor.codeEditor[defaultEditor];
|
||||
initialised = selectedCodeEditor.init();
|
||||
}
|
||||
}
|
||||
|
||||
function create(options) {
|
||||
//TODO: (quandry - for consideration)
|
||||
// Below, I had to create a hidden element if options.id || options.element is not in the DOM
|
||||
// I have seen 1 node calling `this.editor = RED.editor.createEditor()` with an
|
||||
// invalid (non existing html element selector) (e.g. node-red-contrib-components does this)
|
||||
// This causes monaco to throw an error when attempting to hook up its events to the dom & the rest of the 'oneditperapre'
|
||||
// code is thus skipped.
|
||||
// In ACE mode, creating an ACE editor (with an invalid ID) allows the editor to be created (but obviously there is no UI)
|
||||
// Because one (or more) contrib nodes have left this bad code in place, how would we handle this?
|
||||
// For compatibility, I have decided to create a hidden element so that at least an editor is created & errors do not occur.
|
||||
// IMO, we should warn and exit as it is a coding error by the contrib author.
|
||||
|
||||
if (!options) {
|
||||
console.warn("createEditor() options are missing");
|
||||
options = {};
|
||||
}
|
||||
|
||||
if (this.editor.type === MONACO) {
|
||||
// compatibility (see above note)
|
||||
if (!options.element && !options.id) {
|
||||
options.id = 'node-backwards-compatability-dummy-editor';
|
||||
}
|
||||
options.element = options.element || $("#" + options.id)[0];
|
||||
if (!options.element) {
|
||||
console.warn("createEditor() options.element or options.id is not valid", options);
|
||||
$("#dialog-form").append('<div id="' + options.id + '" style="display: none;" />');
|
||||
}
|
||||
return this.editor.create(options);
|
||||
} else {
|
||||
return this.editor.create(options);//fallback to ACE
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
/**
|
||||
* Get editor settings object
|
||||
* @memberof RED.editor.codeEditor
|
||||
*/
|
||||
get settings() {
|
||||
return RED.settings.get('codeEditor') || DEFAULT_SETTINGS;
|
||||
},
|
||||
/**
|
||||
* Get user selected code editor
|
||||
* @return {string} Returns
|
||||
* @memberof RED.editor.codeEditor
|
||||
*/
|
||||
get editor() {
|
||||
return selectedCodeEditor;
|
||||
},
|
||||
/**
|
||||
* Create a editor ui component
|
||||
* @param {object} options - the editor options
|
||||
* @memberof RED.editor.codeEditor
|
||||
*/
|
||||
create: create
|
||||
}
|
||||
})();
|
153
packages/node_modules/@node-red/editor-client/src/js/ui/editors/code-editors/ace.js
vendored
Normal file
153
packages/node_modules/@node-red/editor-client/src/js/ui/editors/code-editors/ace.js
vendored
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
/**
|
||||
* @namespace RED.editor.codeEditor.ace
|
||||
*/
|
||||
RED.editor.codeEditor.ace = (function() {
|
||||
|
||||
const type = "ace";
|
||||
var initialised = false;
|
||||
var initOptions = {};
|
||||
|
||||
function init(options) {
|
||||
initOptions = options || {};
|
||||
initialised = true;
|
||||
return initialised;
|
||||
}
|
||||
|
||||
function create(options) {
|
||||
var editorSettings = RED.editor.codeEditor.settings || {};
|
||||
var el = options.element || $("#"+options.id)[0];
|
||||
var toolbarRow = $("<div>").appendTo(el);
|
||||
el = $("<div>").appendTo(el).addClass("red-ui-editor-text-container")[0];
|
||||
var editor = window.ace.edit(el);
|
||||
editor.setTheme(editorSettings.theme || initOptions.theme || "ace/theme/tomorrow");
|
||||
var session = editor.getSession();
|
||||
session.on("changeAnnotation", function () {
|
||||
var annotations = session.getAnnotations() || [];
|
||||
var i = annotations.length;
|
||||
var len = annotations.length;
|
||||
while (i--) {
|
||||
if (/doctype first\. Expected/.test(annotations[i].text)) { annotations.splice(i, 1); }
|
||||
else if (/Unexpected End of file\. Expected/.test(annotations[i].text)) { annotations.splice(i, 1); }
|
||||
}
|
||||
if (len > annotations.length) { session.setAnnotations(annotations); }
|
||||
});
|
||||
if (options.mode) {
|
||||
session.setMode(options.mode);
|
||||
}
|
||||
if (options.foldStyle) {
|
||||
session.setFoldStyle(options.foldStyle);
|
||||
} else {
|
||||
session.setFoldStyle('markbeginend');
|
||||
}
|
||||
if (options.options) {
|
||||
editor.setOptions(options.options);
|
||||
} else {
|
||||
editor.setOptions({
|
||||
enableBasicAutocompletion:true,
|
||||
enableSnippets:true,
|
||||
tooltipFollowsMouse: false
|
||||
});
|
||||
}
|
||||
if (options.readOnly) {
|
||||
editor.setOption('readOnly',options.readOnly);
|
||||
editor.container.classList.add("ace_read-only");
|
||||
}
|
||||
if (options.hasOwnProperty('lineNumbers')) {
|
||||
editor.renderer.setOption('showGutter',options.lineNumbers);
|
||||
}
|
||||
editor.$blockScrolling = Infinity;
|
||||
if (options.value) {
|
||||
session.setValue(options.value,-1);
|
||||
}
|
||||
if (options.globals) {
|
||||
setTimeout(function() {
|
||||
if (!!session.$worker) {
|
||||
session.$worker.send("setOptions", [{globals: options.globals, maxerr:1000}]);
|
||||
}
|
||||
},100);
|
||||
}
|
||||
if (options.mode === 'ace/mode/markdown') {
|
||||
$(el).addClass("red-ui-editor-text-container-toolbar");
|
||||
editor.toolbar = RED.editor.customEditTypes['_markdown'].buildToolbar(toolbarRow,editor);
|
||||
if (options.expandable !== false) {
|
||||
var expandButton = $('<button type="button" class="red-ui-button" style="float: right;"><i class="fa fa-expand"></i></button>').appendTo(editor.toolbar);
|
||||
RED.popover.tooltip(expandButton, RED._("markdownEditor.expand"));
|
||||
expandButton.on("click", function(e) {
|
||||
e.preventDefault();
|
||||
var value = editor.getValue();
|
||||
RED.editor.editMarkdown({
|
||||
value: value,
|
||||
width: "Infinity",
|
||||
cursor: editor.getCursorPosition(),
|
||||
complete: function(v,cursor) {
|
||||
editor.setValue(v, -1);
|
||||
editor.gotoLine(cursor.row+1,cursor.column,false);
|
||||
setTimeout(function() {
|
||||
editor.focus();
|
||||
},300);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
var helpButton = $('<button type="button" class="red-ui-editor-text-help red-ui-button red-ui-button-small"><i class="fa fa-question"></i></button>').appendTo($(el).parent());
|
||||
RED.popover.create({
|
||||
target: helpButton,
|
||||
trigger: 'click',
|
||||
size: "small",
|
||||
direction: "left",
|
||||
content: RED._("markdownEditor.format"),
|
||||
autoClose: 50
|
||||
});
|
||||
session.setUseWrapMode(true);
|
||||
}
|
||||
editor._destroy = editor.destroy;
|
||||
editor.destroy = function() {
|
||||
try {
|
||||
this._destroy();
|
||||
} catch (e) { }
|
||||
$(el).remove();
|
||||
$(toolbarRow).remove();
|
||||
}
|
||||
editor.type = type;
|
||||
return editor;
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Editor type
|
||||
* @memberof RED.editor.codeEditor.ace
|
||||
*/
|
||||
get type() { return type; },
|
||||
/**
|
||||
* Editor initialised
|
||||
* @memberof RED.editor.codeEditor.ace
|
||||
*/
|
||||
get initialised() { return initialised; },
|
||||
/**
|
||||
* Initialise code editor
|
||||
* @param {object} options - initialisation options
|
||||
* @memberof RED.editor.codeEditor.ace
|
||||
*/
|
||||
init: init,
|
||||
/**
|
||||
* Create a code editor
|
||||
* @param {object} options - the editor options
|
||||
* @memberof RED.editor.codeEditor.ace
|
||||
*/
|
||||
create: create
|
||||
}
|
||||
})();
|
1219
packages/node_modules/@node-red/editor-client/src/js/ui/editors/code-editors/monaco.js
vendored
Normal file
1219
packages/node_modules/@node-red/editor-client/src/js/ui/editors/code-editors/monaco.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
24
packages/node_modules/@node-red/editor-client/src/vendor/monaco/monaco-bootstrap.js
vendored
Normal file
24
packages/node_modules/@node-red/editor-client/src/vendor/monaco/monaco-bootstrap.js
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
(function() {
|
||||
var _isIE = /MSIE \d|Trident.*rv:/.test(navigator.userAgent);
|
||||
//dont load monaco if IE
|
||||
if(_isIE === false) {
|
||||
var defaultLanguage = 'en-gb';
|
||||
var userLocale = (localStorage.getItem("editor-language") + "")
|
||||
var browserLocale = typeof navigator === "undefined" ? "" : (navigator.language || navigator.userLanguage);
|
||||
var cultureDists = {
|
||||
"zh-cn":"zh-hans",
|
||||
"zh-tw":"zh-hant",
|
||||
"ja":"ja",
|
||||
"ko":"ko",
|
||||
"de":"de",
|
||||
"fr":"fr",
|
||||
"it":"it",
|
||||
"es":"es",
|
||||
"ru":"ru",
|
||||
"en-us":"en-gb"
|
||||
};
|
||||
var uiLanguage = cultureDists[userLocale.toLowerCase()] || cultureDists[browserLocale.toLowerCase()] || defaultLanguage;
|
||||
if(uiLanguage) document.write('<script src="vendor/monaco/dist/locale/' + uiLanguage + '.js"><\/script>');
|
||||
document.write('<script src="vendor/monaco/dist/editor.js"><\/script>');
|
||||
}
|
||||
})();
|
@ -30,10 +30,16 @@
|
||||
{{#page.css}}
|
||||
<link rel="stylesheet" href="{{.}}">
|
||||
{{/page.css}}
|
||||
{{#asset.vendorMonaco}}
|
||||
<link rel="stylesheet" href="vendor/monaco/style.css">
|
||||
{{/asset.vendorMonaco}}
|
||||
</head>
|
||||
<body spellcheck="false">
|
||||
<div id="red-ui-editor"></div>
|
||||
<script src="vendor/vendor.js"></script>
|
||||
{{#asset.vendorMonaco}}
|
||||
<script src="{{ asset.vendorMonaco }}"></script>
|
||||
{{/asset.vendorMonaco}}
|
||||
<script src="{{ asset.red }}"></script>
|
||||
<script src="{{ asset.main }}"></script>
|
||||
{{# page.scripts }}
|
||||
|
Loading…
Reference in New Issue
Block a user