diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2892d44..27b5852 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,7 +4,7 @@ See also [the changelog of monaco-editor](https://github.com/Microsoft/monaco-ed
- update to PrimeFaces 7.0
- update to monaco editor 0.16.2
-- No more uses of `eval`.
+- no more uses of `eval`.
- due to the above: the property `extender` of the `monacoEditor` component, if given,
must now be a valid JavaScript expression evaluating to an extender object. Loading the extender
from an URL is not supported anymore. The recommended way is to define a factory function in
diff --git a/pom.xml b/pom.xml
index e30449c..a65c18e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -228,6 +228,8 @@
ECMASCRIPT_2018
ECMASCRIPT_2015
+ (function(){%output%}).call(window);
+ true
widget.js
${project.basedir}/src/main/
${project.basedir}/target/generated-sources
diff --git a/src/main/js/widget.js b/src/main/js/widget.js
index 18b49d9..05081c7 100644
--- a/src/main/js/widget.js
+++ b/src/main/js/widget.js
@@ -1,415 +1,443 @@
-(function() {
- function getScriptName(label) {
- if (label === 'json') {
- return 'json.worker.js';
+///
+
+function getScriptName(label) {
+ if (label === 'json') {
+ return 'json.worker.js';
+ }
+ if (label === 'css') {
+ return 'css.worker.js';
+ }
+ if (label === 'html') {
+ return 'html.worker.js';
+ }
+ if (label === 'typescript' || label === 'javascript') {
+ return 'ts.worker.js';
+ }
+ return 'editor.worker.js';
+}
+
+function endsWith(string, suffix) {
+ var this_len = string.length;
+ return string.substring(this_len - suffix.length, this_len) === suffix;
+}
+
+function getBaseUrl() {
+ var res = PrimeFaces.resources.getFacesResource("", "", "0");
+ var idx = res.lastIndexOf(".xhtml");
+ return idx >= 0 ? res.substring(0, idx) : res;
+}
+
+/**
+ * @param {string} url URL from which to load the script.
+ * @return {Promise} The loaded JavaScript.
+ */
+async function getScript(url) {
+ return jQuery.ajax({
+ type: "GET",
+ url: url,
+ dataType: "script",
+ cache: true,
+ async: true
+ });
+}
+
+/**
+ * Loads the extender for this monaco editor. It may be either
+ *
+ * - an empty string or undefined, in which case no extender is loaded
+ * - a JavaScript expression that evaluates to an extender object
+ * - a path to a resource (eg. `extender.js.xhtml?ln=mylib`) that evaluates to an extender object
+ *
+ * @param {Partial} options The extender string as specified on the component.
+ * @return {Partial}
+ */
+function loadExtender(options) {
+ const extenderString = options.extender;
+
+ // No extender given
+ if (typeof extenderString === "undefined") {
+ return {};
+ }
+
+ // Extender was evaluated already
+ if (typeof extenderString === "object") {
+ return extenderString;
+ }
+
+ // Try creating an extender from the factory
+ if (typeof extenderString === "function") {
+ try {
+ const extender = extenderString();
+ if (typeof extender === "object") {
+ return extender;
+ }
}
- if (label === 'css') {
- return 'css.worker.js';
+ catch (e) {
+ console.warn("Extender must be an expression that evaluates to MonacoExtender", e);
}
- if (label === 'html') {
- return 'html.worker.js';
+ }
+
+ // Could not create extender.
+ console.warn("Extender was specified, but could not be loaded: ", extenderString);
+ return {};
+}
+
+/**
+ * @param {Partial} options
+ * @return {Promise<{forceLibReload: boolean, uiLanguageUri: string}>}
+ */
+async function loadLanguage(options) {
+ // Load language file, if requested.
+ if (options.uiLanguage && MonacoEnvironment.Locale.language !== options.uiLanguage) {
+ // Determine URI for loading the locale.
+ const uri = options.uiLanguageUri ?
+ getBaseUrl() + "uiLanguageUri" :
+ PrimeFaces.resources.getFacesResource("/monacoEditor/locale/" + options.uiLanguage + ".js", "primefaces-blutorange", options.version);
+ // And load UI language
+ await getScript(uri);
+ return {
+ forceLibReload: true,
+ uiLanguageUri: uri,
+ };
+ }
+ else {
+ return {
+ forceLibReload: MonacoEnvironment.Locale.language !== options.uiLanguage,
+ uiLanguageUri: ""
+ };
+ }
+}
+
+/**
+ * @param {Partial} options
+ * @param {boolean} forceLibReload If true, loads the monaco editor again, even if it is loaded already. This is necessary in case the language changes.
+ * @return {Promise} Whether the monaco library was (re)loaded.
+ */
+async function loadEditorLib(options, forceLibReload) {
+ if (!("monaco" in window) || forceLibReload) {
+ if (!options.uiLanguage) {
+ MonacoEnvironment.Locale = {
+ language: "",
+ data: {},
+ };
}
- if (label === 'typescript' || label === 'javascript') {
- return 'ts.worker.js';
+ const uriEditor = PrimeFaces.resources.getFacesResource("/monacoEditor/editor.js", "primefaces-blutorange", options.version);
+ await getScript(uriEditor);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+/**
+ * Evaluate the `beforeCreate` callback of the extender. It is passed the current options and may
+ *
+ * - not return anything, in which case the passed options are used (which may have been modified inplace)
+ * - return an options object, in which case these options are used
+ * - return a promise, in which case the editor is initialized only once that promise resolves. The promise
+ * may resolve to a new options object to be used.
+ *
+ * @param {ExtMonacoEditor} widget
+ * @param {MonacoExtender} extender
+ * @param {boolean} wasLibLoaded
+ * @return {Promise}
+ */
+async function createEditorConstructionOptions(widget, extender, wasLibLoaded) {
+ const editorOptions = typeof widget.options.editorOptions === "object" ?
+ widget.options.editorOptions :
+ typeof widget.options.editorOptions === "string" ?
+ JSON.parse(widget.options.editorOptions) :
+ {};
+
+ const model = createModel(widget.options, widget.id, widget.getInput().val());
+ const options = jQuery.extend({
+ readOnly: widget.options.readonly || widget.options.disabled,
+ model: model,
+ }, editorOptions);
+
+ if (typeof extender.beforeCreate === "function") {
+ const result = extender.beforeCreate(widget, options, wasLibLoaded);
+ if (typeof result === "object") {
+ return typeof result.then === "function" ? (await result) || result : result;
}
- return 'editor.worker.js';
}
- function endsWith(string, suffix) {
- var this_len = string.length;
- return string.substring(this_len - suffix.length, this_len) === suffix;
- }
+ return options;
+}
+
+/**
+ * @param {Partial} options
+ * @param {string} id
+ * @param {string} value
+ * @returns {monaco.editor.ITextModel}
+ */
+function createModel(options, id, value = "") {
+ const language = options.language || "plaintext";
+
+ // Path, basename and extension
+ /** @type {string} */
+ let dir;
+ /** @type {string} */
+ let basename;
+ /** @type {string} */
+ let extension;
+
+ if (options.directory) {
+ dir = options.directory;
+ }
+ else {
+ dir = String(id).replace(/[^a-zA-Z0-9_-]/g, "/");
+ }
+ if (basename) {
+ basename = options.basename;
+ }
+ else {
+ basename = "file";
+ }
+ if (options.ext) {
+ extension = options.ext;
+ }
+ else {
+ const langInfo = monaco.languages.getLanguages().filter(lang => lang.id === language)[0];
+ extension = langInfo && langInfo.extensions.length > 0 ? langInfo.extensions[0] : "";
+ }
- function getScript(url) {
- return jQuery.ajax({
- type: "GET",
- url: url,
- dataType: "script",
- cache: true,
- async: true
- });
+ // Build path and uri
+ if (dir.length > 0 && dir[dir.length - 1] !== "/") {
+ dir = dir + "/";
+ }
+ if (extension.length > 0 && extension[0] !== ".") {
+ extension = "." + extension;
+ }
+ if (endsWith(basename, extension)) {
+ extension = "";
}
- PrimeFaces.widget.ExtMonacoEditor = PrimeFaces.widget.BaseWidget.extend({
- init(cfg) {
- this._super(cfg);
+ const uri = monaco.Uri.from({
+ scheme: "inmemory",
+ path: dir + basename + extension
+ });
- this.$input = this.jq.find(".ui-helper-hidden-accessible textarea");
- this.$editor = this.jq.children(".ui-monaco-editor-ed");
- this.uiLanguageUri = "";
+ // Create model and set value
+ let model = monaco.editor.getModel(uri);
+ if (!model) {
+ model = monaco.editor.createModel(value, language, uri);
+ }
+ model.setValue(value);
+ return model;
+}
+
+
+/**
+ * Default options for the monaco editor widget configuration.
+ */
+const EditorDefaults = {
+ autoResize: false,
+ basename: "",
+ directory: "",
+ disabled: false,
+ editorOptions: {},
+ extender: "",
+ extension: "",
+ language: "plaintext",
+ readonly: false,
+ uiLanguage: "",
+ uiLanguageUri: "",
+ version: "1.0",
+};
+
+// Make sure the monaco environment is set.
+const MonacoEnvironment = window.MonacoEnvironment = window.MonacoEnvironment || {};
+
+class ExtMonacoEditor extends PrimeFaces.widget.BaseWidget {
+ /**
+ * @param {...any[]} args Arguments as passed by PrimeFaces.
+ */
+ constructor(...args) {
+ super(...args);
+ /* super calls #init
+ this._editor = undefined;
+ this._editorContainer = $();
+ this._extenderInstance = undefined;
+ this._input = jQuery();
+ this._resizeObserver = undefined;
+ this._resolvedUiLanguageUri = "";
+ this.options = jQuery.extend({}, EditorDefaults);
+ */
+ }
- // Remove any existing editor.
- this.destroy();
+ init(cfg) {
+ super.init(cfg);
- // Set defaults.
- this.options = jQuery.extend({}, this._defaults, this.cfg);
+ // Set defaults.
+ this.options = jQuery.extend({}, EditorDefaults, this.cfg);
- // English is the default.
- if (this.options.uiLanguage === "en") {
- this.options.uiLanguage = "";
- }
+ // Get elements
+ this._input = this.jq.find(".ui-helper-hidden-accessible textarea");
+ this._editorContainer = this.jq.children(".ui-monaco-editor-ed");
- // Set monaco environment
- window.MonacoEnvironment = window.MonacoEnvironment || {};
- if (!("getWorker" in MonacoEnvironment)) {
- MonacoEnvironment.getWorker = this._createWorkerFactory();
- }
- if (!("Locale" in MonacoEnvironment)) {
- MonacoEnvironment.Locale = {language: "", data: {}};
- }
+ // Remove any existing editor.
+ this.destroy();
- this._loadExtender(true);
- },
-
- /**
- * @return {monaco.editor} Instance of the monacor editor, or undefined if this widget is not yet initialized.
- */
- getMonaco() {
- return this._editor;
- },
-
- /**
- * Loads the extender for this monaco editor. It may be either
- *
- * - an empty string or undefined, in which case no extender is loaded
- * - a JavaScript expression that evaluates to an extender object
- * - a path to a resource (eg. `extender.js.xhtml?ln=mylib`) that evaluates to an extender object
- * @param wasLibLoaded
- * @private
- */
- _loadExtender() {
- this._evaluatedExtender = {};
-
- // No extender given
- if (typeof this.options.extender === "undefined") {
- this._loadLanguage();
- return;
- }
+ // English is the default.
+ if (this.options.uiLanguage === "en") {
+ this.options.uiLanguage = "";
+ }
- // Extender was evaluated already
- if (typeof this.options.extender === "object") {
- this._evaluatedExtender = this.options.extender;
- this._loadLanguage();
- return;
- }
-
- // Try creating an extender from the factory
- var extenderFound = false;
- if (typeof this.options.extender === "function") {
- try {
- this._evaluatedExtender = this.options.extender();
- extenderFound = true;
- }
- catch (e) {
- console.warn("Extender must be an expression that evaluates to MonacoExtender");
- }
- }
+ // Set monaco environment
+ if (!("getWorker" in MonacoEnvironment)) {
+ MonacoEnvironment.getWorker = this._createWorkerFactory();
+ }
+ if (!("Locale" in MonacoEnvironment)) {
+ MonacoEnvironment.Locale = {
+ data: {},
+ language: "",
+ };
+ }
- if (extenderFound) {
- this._loadLanguage();
- return;
- }
+ // Begin loading the editor
+ this._setup().then(() => {
+ this._fireEvent("initialized");
+ this.jq.data("initialized", true);
+ }).catch(error => {
+ console.error("Failed to initialize monaco editor", error);
+ });
+ }
- console.warn("Extender was specified, but could not be loaded");
- this._loadLanguage();
- },
-
- _loadLanguage() {
- // Load language file, if requested.
- if (this.options.uiLanguage && MonacoEnvironment.Locale.language !== this.options.uiLanguage) {
- // Determine URI for loading the locale.
- if (this.options.uiLanguageUri) {
- this.uiLanguageUri = this._getBaseUrl() + this.options.uiLanguageUri;
- }
- else {
- this.uiLanguageUri = PrimeFaces.resources.getFacesResource("/monacoEditor/locale/" + this.options.uiLanguage + ".js", "primefaces-blutorange", this.options.version);
- }
- // Load UI language
- getScript(this.uiLanguageUri).then(() => this._loadEditor(true)).catch(error => {
- console.warn("Failed to load locale for " + this.options.uiLanguage, error);
- this._loadEditor(MonacoEnvironment.Locale.language !== this.options.uiLanguage);
- });
- }
- else {
- this._loadEditor(MonacoEnvironment.Locale.language !== this.options.uiLanguage);
- }
- },
-
- /**
- *
- * @param forceLibReload If true, loads the monaco editor again, even if it is loaded already. This is necessary in case the language changes.
- * @private
- */
- _loadEditor(forceLibReload) {
- if (window.monaco === undefined || forceLibReload) {
- if (this.options.uiLanguage == "") {
- MonacoEnvironment.Locale = {language: "", data: {}};
- }
- var uriEditor = PrimeFaces.resources.getFacesResource("/monacoEditor/editor.js", "primefaces-blutorange", this.options.version);
- getScript(uriEditor).then(() => this._beforeCreate(true)).catch(error => {
- console.warn("Failed to load monaco editor resources, cannot initialize editor", error);
- });
- }
- else {
- this._beforeCreate(false);
- }
- },
-
- /**
- * Evaluate the `beforeCreate` callback of the extender. It is passed the current options and may
- *
- * - not return anything, in which case the passed options are used (which may have been modified inplace)
- * - return an options object, in which case these options are used
- * - return a promise, in which case the editor is initialized only once that promise resolves. The promise
- * may resolve to an new options object to be used.
- * @param wasLibLoaded
- * @private
- */
- _beforeCreate (wasLibLoaded) {
- this._getEditorContainer().empty();
-
- const extender = this._evaluatedExtender;
-
- const editorOptions = typeof this.options.editorOptions === "object" ?
- this.options.editorOptions :
- typeof this.options.editorOptions === "string" ?
- JSON.parse(this.options.editorOptions) :
- {};
-
- const model = this._createModel(editorOptions);
-
- const options = jQuery.extend({
- readOnly: this.options.readonly || this.options.disabled,
- model: model,
-
- // TODO Remove this in version 0.17
- language: this.options.language || "plaintext",
- value: this._getInput().val() || ""
- }, editorOptions);
-
- if (typeof extender.beforeCreate === "function") {
- const result = extender.beforeCreate(this, options, wasLibLoaded);
- if (typeof result === "object") {
- if (typeof result.then === "function") {
- // Promise / thenable returned
- const thened = result.then(newOptions => {
- this._render(typeof newOptions === "object" ? newOptions : options, extender, wasLibLoaded);
- });
- if (typeof thened.catch === "function") {
- thened.catch(error => console.error("Extender promise failed to resolve", error));
- }
- }
- else {
- this._render(result, extender, wasLibLoaded);
- }
- }
- else {
- this._render(options, extender, wasLibLoaded);
- }
- }
- else {
- this._render(options, extender, wasLibLoaded);
- }
- },
+ /**
+ * @return {monaco.editor.IStandaloneCodeEditor} Instance of the monacor editor, or undefined if this widget is not yet initialized.
+ */
+ getMonaco() {
+ return this._editor;
+ }
- _render(options, extender, wasLibLoaded) {
- // TODO Remove this in version 0.17
- if (typeof options.value !== undefined) {
- delete options.value;
- }
- if (typeof options.language !== undefined) {
- delete options.language;
- }
+ destroy() {
+ const extender = this._extenderInstance;
+ const monaco = this.getMonaco();
+ if (extender && typeof extender.beforeDestroy === "function") {
+ extender.beforeDestroy(this);
+ }
+ if (this._resizeObserver !== undefined) {
+ this._resizeObserver.disconnect(this.jq.get(0));
+ }
+ if (monaco !== undefined) {
+ monaco.dispose();
+ }
+ if (extender && typeof extender.afterDestroy === "function") {
+ extender.afterDestroy(this);
+ }
+ }
- // Create a new editor instance.
- this._editor = monaco.editor.create(this._getEditorContainer().get(0), options);
+ /**
+ * @returns {jQuery} The hidden textarea holding the value.
+ */
+ getInput() {
+ return this._input;
+ }
- // Evaluate the `afterCreate` callback of the extender.
- if (typeof extender.afterCreate === "function") {
- extender.afterCreate(this, wasLibLoaded);
- }
+ /**
+ * @returns {jQuery} The element holding the editor.
+ */
+ getEditorContainer() {
+ return this._editorContainer;
+ }
- if (this.options.autoResize) {
- if (typeof window.ResizeObserver === "function") {
- this.resizeObserver = new ResizeObserver(this._onResize.bind(this));
- this.resizeObserver.observe(this.jq.get(0));
- }
- else {
- console.warn("Browser environment does not support autoresize. window.ResizeObserver is not defined.");
- }
+ async _setup() {
+ const extender = loadExtender(this.options);
+ this._extenderInstance = extender;
+ const {forceLibReload, uiLanguageUri} = await loadLanguage(this.options);
+ this._resolvedUiLanguageUri = uiLanguageUri;
+ const wasLibLoaded = await loadEditorLib(this.options, forceLibReload);
+ this.getEditorContainer().empty();
+ const editorConstructionOptions = await createEditorConstructionOptions(this, extender, wasLibLoaded);
+ this._render(editorConstructionOptions, extender, wasLibLoaded);
+ return;
+ }
+
+ /**
+ *
+ * @param {monaco.editor.IEditorConstructionOptions} options
+ * @param {MonacoExtender} extender
+ * @param {boolean} wasLibLoaded
+ */
+ _render(options, extender, wasLibLoaded) {
+ // Create a new editor instance.
+ this._editor = monaco.editor.create(this.getEditorContainer().get(0), options);
+
+ // Evaluate the `afterCreate` callback of the extender.
+ if (typeof extender.afterCreate === "function") {
+ extender.afterCreate(this, wasLibLoaded);
+ }
+
+ // Resize
+ if (this.options.autoResize) {
+ if (typeof ResizeObserver === "function") {
+ this._resizeObserver = new ResizeObserver(this._onResize.bind(this));
+ this._resizeObserver.observe(this.jq.get(0));
+ }
+ else {
+ console.warn("Browser environment does not support autoresize. window.ResizeObserver is not defined.");
}
+ }
- // Change event.
- // Set the value of the editor on the hidden textarea.
- this._editor.onDidChangeModelContent(changes => {
- this._getInput().val(this.getMonaco().getModel().getValue());
- this._fireEvent('change', changes);
- });
+ // Change event.
+ // Set the value of the editor on the hidden textarea.
+ this._editor.onDidChangeModelContent(changes => {
+ this.getInput().val(this.getMonaco().getModel().getValue());
+ this._fireEvent('change', changes);
+ });
- // Focus / blur
- this._editor.onDidFocusEditorWidget(() => this._fireEvent('focus'));
- this._editor.onDidBlurEditorWidget(() => this._fireEvent('blur'));
+ // Focus / blur
+ this._editor.onDidFocusEditorWidget(() => this._fireEvent('focus'));
+ this._editor.onDidBlurEditorWidget(() => this._fireEvent('blur'));
- // Paste
- this._editor.onDidPaste(range => this._fireEvent('paste', range));
+ // Paste
+ this._editor.onDidPaste(range => this._fireEvent('paste', range));
- // Mouse / Key
- this._editor.onMouseDown(mouseEvent => this._fireEvent('mousedown', mouseEvent));
- this._editor.onMouseMove(mouseEvent => this._fireEvent('mousemove', mouseEvent));
- this._editor.onMouseUp(mouseEvent => this._fireEvent('mouseup', mouseEvent));
- this._editor.onKeyDown(keyboardEvent => this._fireEvent('keydown', keyboardEvent));
- this._editor.onKeyUp(keyboardEvent => this._fireEvent('keyup', keyboardEvent));
- this._editor.onDidType(key => this._fireEvent('keypress', key));
+ // Mouse / Key
+ this._editor.onMouseDown(mouseEvent => this._fireEvent('mousedown', mouseEvent));
+ this._editor.onMouseMove(mouseEvent => this._fireEvent('mousemove', mouseEvent));
+ this._editor.onMouseUp(mouseEvent => this._fireEvent('mouseup', mouseEvent));
+ this._editor.onKeyDown(keyboardEvent => this._fireEvent('keydown', keyboardEvent));
+ this._editor.onKeyUp(keyboardEvent => this._fireEvent('keyup', keyboardEvent));
+ this._editor.onDidType(key => this._fireEvent('keypress', key));
+ }
- this._fireEvent("initialized");
- this.jq.data("initialized", true);
- },
-
- destroy() {
- var extender = this._evaluatedExtender;
- if (extender && typeof extender.beforeDestroy === "function") {
- extender.beforeDestroy(this);
- }
- var monaco = this.getMonaco();
- if (this.resizeObserver !== undefined) {
- this.resizeObserver.disconnect(this.jq.get(0));
- }
- if (monaco !== undefined) {
- monaco.dispose();
- }
- if (extender && typeof extender.afterDestroy === "function") {
- extender.afterDestroy(this);
- }
- },
-
- _onResize() {
- var monaco = this.getMonaco();
- if (monaco !== undefined) {
- monaco.layout();
- }
- },
-
- _getBaseUrl() {
- var res = PrimeFaces.resources.getFacesResource("", "", "0");
- var idx = res.lastIndexOf(".xhtml");
- return idx >= 0 ? res.substring(0, idx) : res;
- },
-
- _fireEvent (eventName, ...params) {
- var onName = "on" + eventName;
- this.jq.trigger("monacoEditor:" + eventName, params);
- if (typeof this.options[onName] === "function") {
- this.options[onName].apply(this, params || []);
- }
- this.callBehavior(eventName, {
- params: params || {}
- });
- },
-
- /**
- * @return {(moduleId: string, label: string) => Worker} The factory that creates the workers for JSON, CSS and other languages.
- */
- _createWorkerFactory() {
- return (moduleId, label) => {
- const extender = this._evaluatedExtender;
- if (typeof extender === "object" && typeof extender.createWorker === "function") {
- return extender.createWorker(this, moduleId, label);
- }
- else {
- const workerUrl = PrimeFaces.resources.getFacesResource("monacoEditor/" + getScriptName(label), "primefaces-blutorange", this.options.version);
- const interceptWorkerUrl = PrimeFaces.resources.getFacesResource("monacoEditor/worker.js", "primefaces-blutorange", this.options.version);
- return new Worker(interceptWorkerUrl + "&worker=" + encodeURIComponent(workerUrl) + "&locale=" + encodeURIComponent(this.uiLanguageUri || ""));
- }
- };
- },
-
- _createModel(editorOptions) {
- // Value and language
- var value = this._getInput().val() || "";
- var language = this.options.language || "plaintext";
-
- // Path, basename and extension
- /** @type {string} */
- var dir;
- /** @type {string} */
- var basename;
- /** @type {string} */
- var extension;
- if (this.options.directory) {
- dir = this.options.directory;
- }
- else {
- dir = String(this.id).replace(/[^a-zA-Z0-9_-]/g, "/");
- }
- if (this.options.basename) {
- basename = this.options.basename;
- }
- else {
- basename = "file";
- }
- if (this.options.extension) {
- extension = this.options.extension;
- }
- else {
- var langInfo = monaco.languages.getLanguages().filter(lang => lang.id === language)[0];
- extension = langInfo && langInfo.extensions.length > 0 ? langInfo.extensions[0] : "";
- }
-
- // Build path and uri
- if (dir.length > 0 && dir[dir.length - 1] !== "/") {
- dir = dir + "/";
- }
- if (extension.length > 0 && extension[0] !== ".") {
- extension = "." + extension;
- }
- if (endsWith(basename, extension)) {
- extension = "";
- }
- var uri = monaco.Uri.from({
- scheme: "inmemory",
- path: dir + basename + extension
- });
-
- // Return model
- var model = monaco.editor.getModel(uri);
- if (model) {
- model.setValue(value);
- return model;
+ _onResize() {
+ const monaco = this.getMonaco();
+ if (monaco !== undefined) {
+ monaco.layout();
+ }
+ }
+
+ _fireEvent(eventName, ...params) {
+ var onName = "on" + eventName;
+ this.jq.trigger("monacoEditor:" + eventName, params);
+ if (typeof this.options[onName] === "function") {
+ this.options[onName].apply(this, params || []);
+ }
+ this.callBehavior(eventName, {
+ params: params || {}
+ });
+ }
+
+ /**
+ * @return {(moduleId: string, label: string) => Worker} The factory that creates the workers for JSON, CSS and other languages.
+ */
+ _createWorkerFactory() {
+ return (moduleId, label) => {
+ const extender = this._extenderInstance;
+ if (typeof extender === "object" && typeof extender.createWorker === "function") {
+ return extender.createWorker(this, moduleId, label);
}
else {
- return monaco.editor.createModel(value, language, uri);
+ const workerUrl = PrimeFaces.resources.getFacesResource("monacoEditor/" + getScriptName(label), "primefaces-blutorange", this.options.version);
+ const interceptWorkerUrl = PrimeFaces.resources.getFacesResource("monacoEditor/worker.js", "primefaces-blutorange", this.options.version);
+ return new Worker(interceptWorkerUrl + "&worker=" + encodeURIComponent(workerUrl) + "&locale=" + encodeURIComponent(this._resolvedUiLanguageUri || ""));
}
- },
-
- /**
- * @returns {jQuery} The hidden textarea holding the value.
- * @private
- */
- _getInput() {
- return this.$input;
- },
-
- /**
- * @returns {jQuery} The element holding the editor.
- * @private
- */
- _getEditorContainer() {
- return this.$editor;
- },
-
- _defaults: {
- autoResize: false,
- basename: "",
- directory: "",
- disabled: false,
- editorOptions: {},
- extender: "",
- extension: "",
- language: "plaintext",
- readonly: false,
- uiLanguage: "",
- uiLanguageUri: "",
- version: "1.0"
- },
- });
-})();
+ };
+ }
+}
+
+PrimeFaces.widget.ExtMonacoEditor = ExtMonacoEditor;
diff --git a/src/npm/generateLocales.js b/src/npm/generateLocales.js
index f5c479d..553a9b2 100644
--- a/src/npm/generateLocales.js
+++ b/src/npm/generateLocales.js
@@ -33,53 +33,53 @@ const missingTranslations = {
"singleSelection": ["vs/workbench/browser/parts/editor/editorStatus", "singleSelection"],
"multiSelectionRange": ["vs/workbench/browser/parts/editor/editorStatus", "multiSelectionRange"],
"multiSelection": ["vs/workbench/browser/parts/editor/editorStatus", "multiSelectionRange"],
- "ShowAccessibilityHelpAction": ["vs/workbench/parts/codeEditor/electron-browser/accessibility", "ShowAccessibilityHelpAction"],
+ "ShowAccessibilityHelpAction": ["vs/workbench/contrib/codeEditor/browser/accessibility/accessibility", "ShowAccessibilityHelpAction"],
},
"vs/editor/standalone/browser/inspectTokens/inspectTokens": {
"inspectTokens": "Developer: Inspect Tokens"
},
"vs/editor/standalone/browser/quickOpen/quickOutline": {
"quickOutlineActionInput": "Type the name of an identifier you wish to navigate to",
- "QuickOutlineAction.label": ["vs/workbench/parts/quickopen/browser/quickopen.contribution", "gotoSymbolDescription"],
- "symbols": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "symbols"],
- "method": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "method"],
- "function": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "function"],
- "_constructor": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "_constructor"],
- "variable": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "variable"],
- "class": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "class"],
- "interface": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "interface"],
- "namespace": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "namespace"],
- "package": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "package"],
- "modules": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "modules"],
- "property": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "property"],
- "enum": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "enum"],
- "string": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "string"],
- "rule": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "rule"],
- "file": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "file"],
- "array": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "array"],
- "number": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "number"],
- "boolean": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "boolean"],
- "object": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "object"],
- "key": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "key"],
- "entryAriaLabel": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "entryAriaLabel"],
- "modules": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "modules"],
- "noSymbolsMatching": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "noSymbolsMatching"],
- "noSymbolsFound": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "noSymbolsFound"],
- "gotoSymbolHandlerAriaLabel": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "gotoSymbolHandlerAriaLabel"],
- "cannotRunGotoSymbolInFile": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "cannotRunGotoSymbolInFile"],
- "cannotRunGotoSymbol": ["vs/workbench/parts/quickopen/browser/gotoSymbolHandler", "cannotRunGotoSymbol"],
+ "QuickOutlineAction.label": ["vs/workbench/contrib/quickopen/browser/quickopen.contribution", "gotoSymbolDescription"],
+ "symbols": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "symbols"],
+ "method": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "method"],
+ "function": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "function"],
+ "_constructor": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "_constructor"],
+ "variable": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "variable"],
+ "class": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "class"],
+ "interface": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "interface"],
+ "namespace": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "namespace"],
+ "package": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "package"],
+ "modules": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "modules"],
+ "property": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "property"],
+ "enum": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "enum"],
+ "string": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "string"],
+ "rule": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "rule"],
+ "file": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "file"],
+ "array": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "array"],
+ "number": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "number"],
+ "boolean": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "boolean"],
+ "object": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "object"],
+ "key": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "key"],
+ "entryAriaLabel": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "entryAriaLabel"],
+ "modules": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "modules"],
+ "noSymbolsMatching": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "noSymbolsMatching"],
+ "noSymbolsFound": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "noSymbolsFound"],
+ "gotoSymbolHandlerAriaLabel": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "gotoSymbolHandlerAriaLabel"],
+ "cannotRunGotoSymbolInFile": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "cannotRunGotoSymbolInFile"],
+ "cannotRunGotoSymbol": ["vs/workbench/contrib/quickopen/browser/gotoSymbolHandler", "cannotRunGotoSymbol"],
},
"vs/editor/standalone/browser/quickOpen/gotoLine": {
- "gotoLineLabelEmptyWithLineLimit": ["vs/workbench/parts/quickopen/browser/gotoLineHandler", "gotoLineLabelEmptyWithLimit"],
- "gotoLineAriaLabel": ["vs/workbench/parts/quickopen/browser/gotoLineHandler", "gotoLineLabel"],
- "gotoLineLabelValidLine": ["vs/workbench/parts/quickopen/browser/gotoLineHandler", "gotoLineLabel"],
- "gotoLineActionInput": ["vs/workbench/parts/quickopen/browser/gotoLineHandler", "gotoLineLabelEmpty"],
- "GotoLineAction.label": ["vs/workbench/parts/quickopen/browser/gotoLineHandler", "gotoLine"],
+ "gotoLineLabelEmptyWithLineLimit": ["vs/workbench/contrib/quickopen/browser/gotoLineHandler", "gotoLineLabelEmptyWithLimit"],
+ "gotoLineAriaLabel": ["vs/workbench/contrib/quickopen/browser/gotoLineHandler", "gotoLineLabel"],
+ "gotoLineLabelValidLine": ["vs/workbench/contrib/quickopen/browser/gotoLineHandler", "gotoLineLabel"],
+ "gotoLineActionInput": ["vs/workbench/contrib/quickopen/browser/gotoLineHandler", "gotoLineLabelEmpty"],
+ "GotoLineAction.label": ["vs/workbench/contrib/quickopen/browser/gotoLineHandler", "gotoLine"],
},
"vs/editor/standalone/browser/quickOpen/quickCommand": {
"quickCommandActionInput": "Type the name of an action you want to execute",
- "QuickCommandAction.label": ["vs/workbench/parts/quickopen/browser/quickopen.contribution", "miCommandPalette"],
- "ariaLabelEntry": ["vs/workbench/parts/quickopen/browser/commandsHandler", "entryAriaLabel"],
+ "QuickCommandAction.label": ["vs/workbench/contrib/quickopen/browser/quickopen.contribution", "miCommandPalette"],
+ "ariaLabelEntry": ["vs/workbench/contrib/quickopen/browser/commandsHandler", "entryAriaLabel"],
},
"vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast": {
"toggleHighContrast": "Toggle High Contrast Theme"
diff --git a/src/npm/primefaces-monaco.d.ts b/src/npm/primefaces-monaco.d.ts
index f190f3f..4445eec 100644
--- a/src/npm/primefaces-monaco.d.ts
+++ b/src/npm/primefaces-monaco.d.ts
@@ -42,15 +42,19 @@ export interface MonacoExtender {
* See [IEditorConstructionOptions](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.ieditorconstructionoptions.html) for all editor options.
* @param editorWidget The current monaco editor widget. Note that calling `getMonaco()` on the editor widget right now returns `undefined`.
* @param options The current options that would be used to create the editor.
+ * @param wasLibLoaded `true` if the monaco editor library was reloaded, `false` otherwise. In case it was reloaded, you
+ * may want to setup some language defaults again.
* @return Nothing to use the options as passed; a new options object to be used for creating the editor; or a Promise
* that may return the new options.
*/
- beforeCreate(editorWidget: PrimeFaces.Widget.ExtMonacoEditor, options: monaco.editor.IEditorConstructionOptions): monaco.languages.ProviderResult;
+ beforeCreate(editorWidget: PrimeFaces.Widget.ExtMonacoEditor, options: monaco.editor.IEditorConstructionOptions, wasLibLoaded: boolean): monaco.languages.ProviderResult;
/**
* Called after the editor was created.
* @param editorWidget The current monaco editor widget.
+ * @param wasLibLoaded `true` if the monaco editor library was reloaded, `false` otherwise. In case it was reloaded, you
+ * may want to setup some language defaults again.
*/
- afterCreate(editorWidget: PrimeFaces.Widget.ExtMonacoEditor): void;
+ afterCreate(editorWidget: PrimeFaces.Widget.ExtMonacoEditor, wasLibLoaded: boolean): void;
/**
* Called before the editor is destroyed, eg. when updating a component via AJAX.
* @param editorWidget The current monaco editor widget.
@@ -206,6 +210,12 @@ declare namespace PrimeFaces {
* Destroys this widget. Called by the PrimeFaces framework.
*/
destroy(): void;
+ /**
+ * If it exists, calls the behavior with the given name.
+ * @param name Name of the behavior.
+ * @param args Additional arguments for the behavior.
+ */
+ callBehavior(name: string, ...args: unknown[]): void;
}
/**
* The monaco editor widget. This is a thin wrapper around the actual monaco editor and
@@ -223,6 +233,16 @@ declare namespace PrimeFaces {
* JavaScript. See also the [monaco editor API docs](https://microsoft.github.io/monaco-editor/api/index.html).
*/
getMonaco(): monaco.editor.IStandaloneCodeEditor;
+ /**
+ * @returns {jQuery} The HTML container element holding the editor. It exists even
+ * if the editor was not created yet.
+ */
+ getEditorContainer();
+ /**
+ * @returns {jQuery} The hidden textarea holding the value (eg. what the value sent when
+ * the form is submitted).
+ */
+ getInput();
}
}
}
\ No newline at end of file