diff --git a/amd/build/commands.min.js b/amd/build/commands.min.js
index 4d25d2f..6beee03 100644
--- a/amd/build/commands.min.js
+++ b/amd/build/commands.min.js
@@ -1,3 +1,3 @@
-define("tiny_codepro/commands",["exports","editor_tiny/utils","core/str","./ui","./common","./options"],(function(_exports,_utils,_str,_ui,_common,_options){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.getSetup=void 0;_exports.getSetup=async()=>{const[pluginName,buttonImage]=await Promise.all([(0,_str.get_string)("pluginname",_common.component),(0,_utils.getButtonImage)("icon",_common.component)]);return editor=>{(0,_options.isPluginVisible)(editor)&&(editor.ui.registry.addIcon(_common.icon,buttonImage.html),editor.ui.registry.addButton(_common.component,{icon:_common.icon,tooltip:pluginName,onAction:()=>(0,_ui.handleAction)(editor),enabled:!1,onSetup:api=>{const cb=()=>api.setEnabled(!0);return editor.on("SetContent",cb),()=>editor.off("SetContent",cb)}}),editor.ui.registry.addMenuItem(_common.component,{icon:_common.icon,text:pluginName,onAction:()=>(0,_ui.handleAction)(editor)}))}}}));
+define("tiny_codepro/commands",["exports","editor_tiny/utils","core/str","./ui","./common","./options"],(function(_exports,_utils,_str,_ui,_common,_options){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.getSetup=void 0;_exports.getSetup=async()=>{const[pluginName,buttonImage]=await Promise.all([(0,_str.get_string)("pluginname",_common.component),(0,_utils.getButtonImage)("icon",_common.component)]);return editor=>{(0,_options.isPluginVisible)(editor)&&(editor.ui.registry.addIcon(_common.icon,buttonImage.html),editor.ui.registry.addButton(_common.component,{icon:_common.icon,tooltip:pluginName,onAction:()=>(0,_ui.handleAction)(editor)}),editor.ui.registry.addMenuItem(_common.component,{icon:_common.icon,text:pluginName,onAction:()=>(0,_ui.handleAction)(editor)}))}}}));
//# sourceMappingURL=commands.min.js.map
\ No newline at end of file
diff --git a/amd/build/commands.min.js.map b/amd/build/commands.min.js.map
index 05a6921..f8bb1ad 100644
--- a/amd/build/commands.min.js.map
+++ b/amd/build/commands.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"commands.min.js","sources":["../src/commands.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Tiny CodePro plugin.\n *\n * @module tiny_codepro/plugin\n * @copyright 2023 Josep Mulet Pol \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {getButtonImage} from 'editor_tiny/utils';\nimport {get_string as getString} from 'core/str';\nimport {handleAction} from './ui';\nimport {component, icon} from './common';\nimport {isPluginVisible} from './options';\n\nexport const getSetup = async() => {\n const [\n pluginName,\n buttonImage,\n ] = await Promise.all([\n getString('pluginname', component),\n getButtonImage('icon', component),\n ]);\n\n return (editor) => {\n if (!isPluginVisible(editor)) {\n return;\n }\n // Register the Icon.\n editor.ui.registry.addIcon(icon, buttonImage.html);\n\n // Register the Toolbar Button.\n editor.ui.registry.addButton(component, {\n icon,\n tooltip: pluginName,\n onAction: () => handleAction(editor),\n enabled: false,\n onSetup: (api) => {\n const cb = () => api.setEnabled(true);\n editor.on('SetContent', cb);\n return () => editor.off('SetContent', cb);\n }\n });\n\n // Add the Menu Item.\n // This allows it to be added to a standard menu, or a context menu.\n editor.ui.registry.addMenuItem(component, {\n icon,\n text: pluginName,\n onAction: () => handleAction(editor)\n });\n };\n};"],"names":["async","pluginName","buttonImage","Promise","all","component","editor","ui","registry","addIcon","icon","html","addButton","tooltip","onAction","enabled","onSetup","api","cb","setEnabled","on","off","addMenuItem","text"],"mappings":"gQA6BwBA,gBAEhBC,WACAC,mBACMC,QAAQC,IAAI,EAClB,mBAAU,aAAcC,oBACxB,yBAAe,OAAQA,4BAGnBC,UACC,4BAAgBA,UAIrBA,OAAOC,GAAGC,SAASC,QAAQC,aAAMR,YAAYS,MAG7CL,OAAOC,GAAGC,SAASI,UAAUP,kBAAW,CACpCK,KAAAA,aACAG,QAASZ,WACTa,SAAU,KAAM,oBAAaR,QAC7BS,SAAS,EACTC,QAAUC,YACAC,GAAK,IAAMD,IAAIE,YAAW,UAChCb,OAAOc,GAAG,aAAcF,IACjB,IAAMZ,OAAOe,IAAI,aAAcH,OAM9CZ,OAAOC,GAAGC,SAASc,YAAYjB,kBAAW,CACtCK,KAAAA,aACAa,KAAMtB,WACNa,SAAU,KAAM,oBAAaR"}
\ No newline at end of file
+{"version":3,"file":"commands.min.js","sources":["../src/commands.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Tiny CodePro plugin.\n *\n * @module tiny_codepro/plugin\n * @copyright 2023 Josep Mulet Pol \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {getButtonImage} from 'editor_tiny/utils';\nimport {get_string as getString} from 'core/str';\nimport {handleAction} from './ui';\nimport {component, icon} from './common';\nimport {isPluginVisible} from './options';\n\nexport const getSetup = async() => {\n const [\n pluginName,\n buttonImage,\n ] = await Promise.all([\n getString('pluginname', component),\n getButtonImage('icon', component),\n ]);\n\n return (editor) => {\n if (!isPluginVisible(editor)) {\n return;\n }\n // Register the Icon.\n editor.ui.registry.addIcon(icon, buttonImage.html);\n\n // Register the Toolbar Button.\n editor.ui.registry.addButton(component, {\n icon,\n tooltip: pluginName,\n onAction: () => handleAction(editor)\n });\n\n // Add the Menu Item.\n // This allows it to be added to a standard menu, or a context menu.\n editor.ui.registry.addMenuItem(component, {\n icon,\n text: pluginName,\n onAction: () => handleAction(editor)\n });\n };\n};"],"names":["async","pluginName","buttonImage","Promise","all","component","editor","ui","registry","addIcon","icon","html","addButton","tooltip","onAction","addMenuItem","text"],"mappings":"gQA6BwBA,gBAEhBC,WACAC,mBACMC,QAAQC,IAAI,EAClB,mBAAU,aAAcC,oBACxB,yBAAe,OAAQA,4BAGnBC,UACC,4BAAgBA,UAIrBA,OAAOC,GAAGC,SAASC,QAAQC,aAAMR,YAAYS,MAG7CL,OAAOC,GAAGC,SAASI,UAAUP,kBAAW,CACpCK,KAAAA,aACAG,QAASZ,WACTa,SAAU,KAAM,oBAAaR,UAKjCA,OAAOC,GAAGC,SAASO,YAAYV,kBAAW,CACtCK,KAAAA,aACAM,KAAMf,WACNa,SAAU,KAAM,oBAAaR"}
\ No newline at end of file
diff --git a/amd/build/plugin.min.js b/amd/build/plugin.min.js
index e9ddbf4..57cc166 100644
--- a/amd/build/plugin.min.js
+++ b/amd/build/plugin.min.js
@@ -5,6 +5,6 @@ define("tiny_codepro/plugin",["exports","editor_tiny/loader","editor_tiny/utils"
* @module tiny_codepro/plugin
* @copyright 2023 Josep Mulet Pol
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */(Configuration);var _default=new Promise((async resolve=>{const[tinyMCE,pluginMetadata,setupCommands]=await Promise.all([(0,_loader.getTinyMCE)(),(0,_utils.getPluginMetadata)(_common.component,_common.pluginName,"https://github.com/jmulet/moodle-tiny_codepro"),(0,_commands.getSetup)()]);tinyMCE.PluginManager.add(_common.pluginName,(editor=>((0,_options.register)(editor),setupCommands(editor),pluginMetadata))),resolve([_common.pluginName,Configuration])}));return _exports.default=_default,_exports.default}));
+ */(Configuration);var _default=new Promise((async resolve=>{const[tinyMCE,pluginMetadata,setupCommands]=await Promise.all([(0,_loader.getTinyMCE)(),(0,_utils.getPluginMetadata)(_common.component,_common.pluginName,"https://github.com/jmulet/moodle-tiny_codepro"),(0,_commands.getSetup)()]);tinyMCE.PluginManager.add(_common.pluginName,(editor=>((0,_options.register)(editor),editor.once("SetContent",(()=>{setupCommands(editor)})),pluginMetadata))),resolve([_common.pluginName,Configuration])}));return _exports.default=_default,_exports.default}));
//# sourceMappingURL=plugin.min.js.map
\ No newline at end of file
diff --git a/amd/build/plugin.min.js.map b/amd/build/plugin.min.js.map
index 70dbc6b..76fc0e6 100644
--- a/amd/build/plugin.min.js.map
+++ b/amd/build/plugin.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"plugin.min.js","sources":["../src/plugin.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Tiny CodePro plugin.\n *\n * @module tiny_codepro/plugin\n * @copyright 2023 Josep Mulet Pol \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {getTinyMCE} from 'editor_tiny/loader';\nimport {getPluginMetadata} from 'editor_tiny/utils';\n\nimport {component, pluginName} from './common';\nimport {register as registerOptions} from './options';\nimport {getSetup as getCommandSetup} from './commands';\nimport * as Configuration from './configuration';\n\nconst documentationUrl = 'https://github.com/jmulet/moodle-tiny_codepro';\n\n// Setup the Plugin.\n// eslint-disable-next-line no-async-promise-executor\nexport default new Promise(async(resolve) => {\n const [\n tinyMCE,\n pluginMetadata,\n setupCommands,\n ] = await Promise.all([\n getTinyMCE(),\n getPluginMetadata(component, pluginName, documentationUrl),\n getCommandSetup(),\n ]);\n\n tinyMCE.PluginManager.add(pluginName, (editor) => {\n // Register options.\n registerOptions(editor);\n // Resolve the Plugin and include configuration.\n // Setup commands.\n setupCommands(editor);\n return pluginMetadata;\n });\n resolve([pluginName, Configuration]);\n});\n"],"names":["Promise","async","tinyMCE","pluginMetadata","setupCommands","all","component","pluginName","PluginManager","add","editor","resolve","Configuration"],"mappings":";;;;;;;kCAmCe,IAAIA,SAAQC,MAAAA,gBAEnBC,QACAC,eACAC,qBACMJ,QAAQK,IAAI,EAClB,yBACA,4BAAkBC,kBAAWC,mBAXZ,kDAYjB,0BAGJL,QAAQM,cAAcC,IAAIF,oBAAaG,+BAEnBA,QAGhBN,cAAcM,QACPP,kBAEXQ,QAAQ,CAACJ,mBAAYK"}
\ No newline at end of file
+{"version":3,"file":"plugin.min.js","sources":["../src/plugin.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Tiny CodePro plugin.\n *\n * @module tiny_codepro/plugin\n * @copyright 2023 Josep Mulet Pol \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {getTinyMCE} from 'editor_tiny/loader';\nimport {getPluginMetadata} from 'editor_tiny/utils';\n\nimport {component, pluginName} from './common';\nimport {register as registerOptions} from './options';\nimport {getSetup as getCommandSetup} from './commands';\nimport * as Configuration from './configuration';\n\nconst documentationUrl = 'https://github.com/jmulet/moodle-tiny_codepro';\n\n// Setup the Plugin.\n// eslint-disable-next-line no-async-promise-executor\nexport default new Promise(async(resolve) => {\n const [\n tinyMCE,\n pluginMetadata,\n setupCommands,\n ] = await Promise.all([\n getTinyMCE(),\n getPluginMetadata(component, pluginName, documentationUrl),\n getCommandSetup(),\n ]);\n\n tinyMCE.PluginManager.add(pluginName, (editor) => {\n // Register options.\n registerOptions(editor);\n // Resolve the Plugin and include configuration.\n // Setup commands (only if the content has been set) to prevent from opening the modal without content.\n editor.once('SetContent', () => {\n setupCommands(editor);\n });\n return pluginMetadata;\n });\n\n resolve([pluginName, Configuration]);\n});\n"],"names":["Promise","async","tinyMCE","pluginMetadata","setupCommands","all","component","pluginName","PluginManager","add","editor","once","resolve","Configuration"],"mappings":";;;;;;;kCAmCe,IAAIA,SAAQC,MAAAA,gBAEnBC,QACAC,eACAC,qBACMJ,QAAQK,IAAI,EAClB,yBACA,4BAAkBC,kBAAWC,mBAXZ,kDAYjB,0BAGJL,QAAQM,cAAcC,IAAIF,oBAAaG,+BAEnBA,QAGhBA,OAAOC,KAAK,cAAc,KACtBP,cAAcM,WAEXP,kBAGXS,QAAQ,CAACL,mBAAYM"}
\ No newline at end of file
diff --git a/amd/build/ui.min.js b/amd/build/ui.min.js
index 584ec4d..bc40221 100644
--- a/amd/build/ui.min.js
+++ b/amd/build/ui.min.js
@@ -5,6 +5,6 @@ define("tiny_codepro/ui",["exports","./modal","core/modal_events","./preferences
* @module tiny_codepro/plugin
* @copyright 2023 Josep Mulet Pol
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.handleAction=void 0,_modal_events=(obj=_modal_events)&&obj.__esModule?obj:{default:obj};let modal=null,codeEditorInstance=null;const toggleClasses=function(el,classList){const cl=el.classList;classList.forEach((className=>{cl.toggle(className)}))};_exports.handleAction=async editor=>{null===modal&&await createDialogue();modal.footer.find("button.btn[data-action]").off("click.codepro").on("click.codepro",(evt=>{if(evt.target.classList.contains("btn-primary")){const updatedCode=codeEditorInstance.getValue({source_view:!0});editor.setContent(updatedCode)}modal.hide(),codeEditorInstance.setValue()}));const markerNode=document.createElement("SPAN");markerNode.innerHTML=" ",markerNode.classList.add("CmCaReT");editor.selection.getStart().append(markerNode);let html=editor.getContent({source_view:!0});html=html.replace(/]*)>([^<]*)<\/span>/gm,String.fromCharCode(0)),markerNode.remove(),(0,_preferences.getPref)("prettify")&&(html=codeEditorInstance.prettifyCode(html)),codeEditorInstance.setValue(html),modal.show(),setTimeout((()=>codeEditorInstance.focus()),500)};const createDialogue=async()=>{const data={elementid:Math.random().toString(32).substring(2)};return modal=await(0,_modal.createModal)({templateContext:data}),modal.getRoot().find(".modal-dialog.modal-lg").addClass("tiny_codepro-dlg"),modal.getRoot().off("keydown"),modal.getRoot().on(_modal_events.default.outsideClick,(evt=>{evt.preventDefault()})),modal.body.css("overflow-y","overlay"),modal.header.css("height","61.46px"),modal.header.css("padding","1rem 1rem"),new Promise((resolve=>{require(["tiny_codepro/cm6pro-lazy"],(CodeProEditor=>{const targetElem=modal.body.find(".tiny_codepro-editor-area")[0];codeEditorInstance=new CodeProEditor(targetElem),modal.footer.find("button.btn.btn-light").on("click",(evt=>{evt.preventDefault();const ds=evt.currentTarget.dataset,icon=evt.currentTarget.querySelector("i.fa"),$dlgElem=modal.getRoot().find('[role="document"], [data-region="modal"]');if(ds.fs)"false"===ds.fs?(ds.fs="true",modal.header.hide(),$dlgElem.removeClass("modal-dialog modal-lg modal-dialog-scrollable"),$dlgElem.addClass("tiny_codepro-fullscreen")):(ds.fs="false",modal.header.show(),$dlgElem.removeClass("tiny_codepro-fullscreen"),$dlgElem.addClass("modal-dialog modal-lg modal-dialog-scrollable")),(0,_preferences.setPref)("fs",ds.fs,!0);else if(ds.theme)"light"===ds.theme?(ds.theme="dark",codeEditorInstance.setTheme("dark"),$dlgElem.addClass("tiny_codepro-dark")):(ds.theme="light",codeEditorInstance.setTheme("light"),$dlgElem.removeClass("tiny_codepro-dark")),toggleClasses(icon,["fa-sun-o","fa-moon-o"]),(0,_preferences.setPref)("theme",ds.theme,!0);else if(ds.wrap)"true"===ds.wrap?(ds.wrap=!1,codeEditorInstance.setLineWrapping(!1)):(ds.wrap=!0,codeEditorInstance.setLineWrapping(!0)),(0,_preferences.setPref)("wrap",ds.wrap,!0),toggleClasses(icon,["fa-exchange","fa-long-arrow-right"]);else if(void 0!==ds.prettify)codeEditorInstance.prettify();else if(void 0!==ds.autoPrettify){(0,_preferences.setPref)("prettify",!(0,_preferences.getPref)("prettify",!1),!0);const icon=evt.currentTarget.querySelector("i");toggleClasses(icon,["fa-times","fa-check"])}})),modal.getRoot().on(_modal_events.default.hidden,(()=>{codeEditorInstance.setValue()}));const currentTheme=(0,_preferences.getPref)("theme","light"),currentWrap=(0,_preferences.getPref)("wrap","false"),currentFs=(0,_preferences.getPref)("fs","false"),currentPrettify=(0,_preferences.getPref)("prettify",!1);"light"!==currentTheme&&modal.footer.find("button.btn.btn-light[data-theme]").click(),"true"===currentWrap&&modal.footer.find("button.btn.btn-light[data-wrap]").click(),"true"===currentFs&&modal.footer.find("button.btn.btn-light[data-fs]").click(),currentPrettify&&modal.footer.find("button.btn.btn-light[data-auto-prettify] > i").removeClass("fa-times").addClass("fa-check"),resolve(modal)}))}))}}));
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.handleAction=void 0,_modal_events=(obj=_modal_events)&&obj.__esModule?obj:{default:obj};let modal=null,codeEditorInstance=null;const toggleClasses=function(el,classList){const cl=el.classList;classList.forEach((className=>{cl.toggle(className)}))};let isLoading=!1;_exports.handleAction=async editor=>{var _codeEditorInstance4;if(isLoading)return;null===modal&&(isLoading=!0,modal=await createDialogue(),isLoading=!1);modal.footer.find("button.btn[data-action]").off("click.codepro").on("click.codepro",(evt=>{var _codeEditorInstance2;if(evt.target.classList.contains("btn-primary")){var _codeEditorInstance;const updatedCode=null===(_codeEditorInstance=codeEditorInstance)||void 0===_codeEditorInstance?void 0:_codeEditorInstance.getValue({source_view:!0});editor.setContent(updatedCode??"")}modal.hide(),null===(_codeEditorInstance2=codeEditorInstance)||void 0===_codeEditorInstance2||_codeEditorInstance2.setValue()}));const markerNode=document.createElement("SPAN");markerNode.innerHTML=" ",markerNode.classList.add("CmCaReT");editor.selection.getStart().append(markerNode);let html=editor.getContent({source_view:!0});var _codeEditorInstance3;(html=html.replace(/]*)>([^<]*)<\/span>/gm,String.fromCharCode(0)),markerNode.remove(),(0,_preferences.getPref)("prettify"))&&(html=null===(_codeEditorInstance3=codeEditorInstance)||void 0===_codeEditorInstance3?void 0:_codeEditorInstance3.prettifyCode(html));null===(_codeEditorInstance4=codeEditorInstance)||void 0===_codeEditorInstance4||_codeEditorInstance4.setValue(html),modal.show(),setTimeout((()=>{var _codeEditorInstance5;return null===(_codeEditorInstance5=codeEditorInstance)||void 0===_codeEditorInstance5?void 0:_codeEditorInstance5.focus()}),500)};const createDialogue=async()=>{const data={elementid:Math.random().toString(32).substring(2)},modal=await(0,_modal.createModal)({templateContext:data});modal.getRoot().find(".modal-dialog.modal-lg").addClass("tiny_codepro-dlg"),modal.getRoot().off("keydown"),modal.getRoot().on(_modal_events.default.outsideClick,(evt=>{evt.preventDefault()})),modal.body.css("overflow-y","overlay"),modal.header.css("height","61.46px"),modal.header.css("padding","1rem 1rem");const CodeProEditor=await new Promise((resolve=>{require(["tiny_codepro/cm6pro-lazy"],(CodeProEditor=>{resolve(CodeProEditor)}))})),targetElem=modal.body.find(".tiny_codepro-editor-area")[0];codeEditorInstance=new CodeProEditor(targetElem),modal.footer.find("button.btn.btn-light").on("click",(evt=>{evt.preventDefault();const ds=evt.currentTarget.dataset,icon=evt.currentTarget.querySelector("i.fa"),$dlgElem=modal.getRoot().find('[role="document"], [data-region="modal"]');if(ds.fs)"false"===ds.fs?(ds.fs="true",modal.header.hide(),$dlgElem.removeClass("modal-dialog modal-lg modal-dialog-scrollable"),$dlgElem.addClass("tiny_codepro-fullscreen")):(ds.fs="false",modal.header.show(),$dlgElem.removeClass("tiny_codepro-fullscreen"),$dlgElem.addClass("modal-dialog modal-lg modal-dialog-scrollable")),(0,_preferences.setPref)("fs",ds.fs,!0);else if(ds.theme)"light"===ds.theme?(ds.theme="dark",codeEditorInstance.setTheme("dark"),$dlgElem.addClass("tiny_codepro-dark")):(ds.theme="light",codeEditorInstance.setTheme("light"),$dlgElem.removeClass("tiny_codepro-dark")),toggleClasses(icon,["fa-sun-o","fa-moon-o"]),(0,_preferences.setPref)("theme",ds.theme,!0);else if(ds.wrap){var _codeEditorInstance6,_codeEditorInstance7;if("true"===ds.wrap)ds.wrap=!1,null===(_codeEditorInstance6=codeEditorInstance)||void 0===_codeEditorInstance6||_codeEditorInstance6.setLineWrapping(!1);else ds.wrap=!0,null===(_codeEditorInstance7=codeEditorInstance)||void 0===_codeEditorInstance7||_codeEditorInstance7.setLineWrapping(!0);(0,_preferences.setPref)("wrap",ds.wrap,!0),toggleClasses(icon,["fa-exchange","fa-long-arrow-right"])}else if(void 0!==ds.prettify){var _codeEditorInstance8;null===(_codeEditorInstance8=codeEditorInstance)||void 0===_codeEditorInstance8||_codeEditorInstance8.prettify()}else if(void 0!==ds.autoPrettify){(0,_preferences.setPref)("prettify",!(0,_preferences.getPref)("prettify",!1),!0);const icon=evt.currentTarget.querySelector("i");toggleClasses(icon,["fa-times","fa-check"])}})),modal.getRoot().on(_modal_events.default.hidden,(()=>{var _codeEditorInstance9;null===(_codeEditorInstance9=codeEditorInstance)||void 0===_codeEditorInstance9||_codeEditorInstance9.setValue()}));const currentTheme=(0,_preferences.getPref)("theme","light"),currentWrap=(0,_preferences.getPref)("wrap","false"),currentFs=(0,_preferences.getPref)("fs","false"),currentPrettify=(0,_preferences.getPref)("prettify",!1);return"light"!==currentTheme&&modal.footer.find("button.btn.btn-light[data-theme]").click(),"true"===currentWrap&&modal.footer.find("button.btn.btn-light[data-wrap]").click(),"true"===currentFs&&modal.footer.find("button.btn.btn-light[data-fs]").click(),currentPrettify&&modal.footer.find("button.btn.btn-light[data-auto-prettify] > i").removeClass("fa-times").addClass("fa-check"),modal}}));
//# sourceMappingURL=ui.min.js.map
\ No newline at end of file
diff --git a/amd/build/ui.min.js.map b/amd/build/ui.min.js.map
index 476b446..ae115df 100644
--- a/amd/build/ui.min.js.map
+++ b/amd/build/ui.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"ui.min.js","sources":["../src/ui.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\nimport {createModal} from \"./modal\";\nimport ModalEvents from 'core/modal_events';\nimport {getPref, setPref} from \"./preferences\";\n\n/**\n * Tiny CodePro plugin.\n *\n * @module tiny_codepro/plugin\n * @copyright 2023 Josep Mulet Pol \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nconst dialogQuery = '[role=\"document\"], [data-region=\"modal\"]';\nlet modal = null;\nlet codeEditorInstance = null;\n\n/**\n * Utility to toggle a class in an HTML element\n * @param {HTMLElement} el - The Element\n * @param {string[]} classList\n */\nconst toggleClasses = function(el, classList) {\n const cl = el.classList;\n classList.forEach(className => {\n cl.toggle(className);\n });\n};\n\n/**\n * Handle action\n * @param {TinyMCE} editor\n */\nexport const handleAction = async(editor) => {\n if (modal === null) {\n await createDialogue();\n }\n\n // Issue, editor var does not get updated\n // Bind save action to the correct editor\n const $btn = modal.footer.find(\"button.btn[data-action]\");\n $btn.off(\"click.codepro\").on(\"click.codepro\", (evt) => {\n if (evt.target.classList.contains(\"btn-primary\")) {\n // eslint-disable-next-line camelcase\n const updatedCode = codeEditorInstance.getValue({source_view: true});\n editor.setContent(updatedCode);\n }\n modal.hide();\n // Delete content\n codeEditorInstance.setValue();\n });\n\n // Insert caret marker and retrieve html code to pass to CodeMirror\n const markerNode = document.createElement(\"SPAN\");\n markerNode.innerHTML = ' ';\n markerNode.classList.add('CmCaReT');\n const currentNode = editor.selection.getStart();\n currentNode.append(markerNode);\n // eslint-disable-next-line camelcase\n let html = editor.getContent({source_view: true});\n html = html.replace(/]*)>([^<]*)<\\/span>/gm, String.fromCharCode(0));\n markerNode.remove();\n\n if (getPref(\"prettify\")) {\n html = codeEditorInstance.prettifyCode(html);\n }\n codeEditorInstance.setValue(html);\n\n modal.show();\n setTimeout(() => codeEditorInstance.focus(), 500);\n};\n\nconst createDialogue = async() => {\n const data = {\n elementid: Math.random().toString(32).substring(2)\n };\n\n // Show modal with buttons.\n modal = await createModal({\n templateContext: data\n });\n\n modal.getRoot().find(\".modal-dialog.modal-lg\").addClass(\"tiny_codepro-dlg\");\n // Disable keyboard events (ESC key) on this modal\n modal.getRoot().off('keydown');\n // Prevent modal from closing on outside clicks\n modal.getRoot().on(ModalEvents.outsideClick, (evt) => {\n evt.preventDefault();\n });\n modal.body.css(\"overflow-y\", \"overlay\");\n // Override styles imposed by body.tox-fullscreen on modals\n modal.header.css('height', '61.46px');\n modal.header.css('padding', '1rem 1rem');\n\n return new Promise((resolve) => {\n // Load cm6 on demand\n require(['tiny_codepro/cm6pro-lazy'], (CodeProEditor) => {\n const targetElem = modal.body.find('.tiny_codepro-editor-area')[0];\n codeEditorInstance = new CodeProEditor(targetElem);\n\n modal.footer.find(\"button.btn.btn-light\").on(\"click\", (evt) => {\n evt.preventDefault();\n const ds = evt.currentTarget.dataset;\n const icon = evt.currentTarget.querySelector(\"i.fa\");\n const $dlgElem = modal.getRoot().find(dialogQuery);\n if (ds.fs) {\n if (ds.fs === \"false\") {\n // Set fullscreen mode\n ds.fs = \"true\";\n modal.header.hide();\n $dlgElem.removeClass(\"modal-dialog modal-lg modal-dialog-scrollable\");\n $dlgElem.addClass(\"tiny_codepro-fullscreen\");\n } else {\n // Set to modal-lg\n ds.fs = \"false\";\n modal.header.show();\n $dlgElem.removeClass(\"tiny_codepro-fullscreen\");\n $dlgElem.addClass(\"modal-dialog modal-lg modal-dialog-scrollable\");\n }\n setPref(\"fs\", ds.fs, true);\n } else if (ds.theme) {\n if (ds.theme === \"light\") {\n ds.theme = \"dark\";\n codeEditorInstance.setTheme(\"dark\");\n $dlgElem.addClass(\"tiny_codepro-dark\");\n } else {\n ds.theme = \"light\";\n codeEditorInstance.setTheme(\"light\");\n $dlgElem.removeClass(\"tiny_codepro-dark\");\n }\n toggleClasses(icon, [\"fa-sun-o\", \"fa-moon-o\"]);\n setPref(\"theme\", ds.theme, true);\n } else if (ds.wrap) {\n if (ds.wrap === \"true\") {\n ds.wrap = false;\n codeEditorInstance.setLineWrapping(false);\n } else {\n ds.wrap = true;\n codeEditorInstance.setLineWrapping(true);\n }\n setPref(\"wrap\", ds.wrap, true);\n toggleClasses(icon, [\"fa-exchange\", \"fa-long-arrow-right\"]);\n } else if (ds.prettify !== undefined) {\n codeEditorInstance.prettify();\n } else if (ds.autoPrettify !== undefined) {\n setPref(\"prettify\", !getPref(\"prettify\", false), true);\n const icon = evt.currentTarget.querySelector(\"i\");\n toggleClasses(icon, [\"fa-times\", \"fa-check\"]);\n }\n });\n\n modal.getRoot().on(ModalEvents.hidden, () => {\n codeEditorInstance.setValue();\n });\n\n // Setting stored preferences\n const currentTheme = getPref(\"theme\", \"light\");\n const currentWrap = getPref(\"wrap\", \"false\");\n const currentFs = getPref(\"fs\", \"false\");\n const currentPrettify = getPref(\"prettify\", false);\n\n if (currentTheme !== \"light\") {\n modal.footer.find(\"button.btn.btn-light[data-theme]\").click();\n }\n if (currentWrap === \"true\") {\n modal.footer.find(\"button.btn.btn-light[data-wrap]\").click();\n }\n if (currentFs === \"true\") {\n modal.footer.find(\"button.btn.btn-light[data-fs]\").click();\n }\n if (currentPrettify) {\n modal.footer.find(\"button.btn.btn-light[data-auto-prettify] > i\")\n .removeClass(\"fa-times\")\n .addClass(\"fa-check\");\n }\n\n resolve(modal);\n });\n });\n};"],"names":["modal","codeEditorInstance","toggleClasses","el","classList","cl","forEach","className","toggle","async","createDialogue","footer","find","off","on","evt","target","contains","updatedCode","getValue","source_view","editor","setContent","hide","setValue","markerNode","document","createElement","innerHTML","add","selection","getStart","append","html","getContent","replace","String","fromCharCode","remove","prettifyCode","show","setTimeout","focus","data","elementid","Math","random","toString","substring","templateContext","getRoot","addClass","ModalEvents","outsideClick","preventDefault","body","css","header","Promise","resolve","require","CodeProEditor","targetElem","ds","currentTarget","dataset","icon","querySelector","$dlgElem","fs","removeClass","theme","setTheme","wrap","setLineWrapping","undefined","prettify","autoPrettify","hidden","currentTheme","currentWrap","currentFs","currentPrettify","click"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"ui.min.js","sources":["../src/ui.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\nimport {createModal} from \"./modal\";\nimport ModalEvents from 'core/modal_events';\nimport {getPref, setPref} from \"./preferences\";\n\n/**\n * Tiny CodePro plugin.\n *\n * @module tiny_codepro/plugin\n * @copyright 2023 Josep Mulet Pol \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nconst dialogQuery = '[role=\"document\"], [data-region=\"modal\"]';\nlet modal = null;\nlet codeEditorInstance = null;\n\n/**\n * Utility to toggle a class in an HTML element\n * @param {HTMLElement} el - The Element\n * @param {string[]} classList\n */\nconst toggleClasses = function(el, classList) {\n const cl = el.classList;\n classList.forEach(className => {\n cl.toggle(className);\n });\n};\n\nlet isLoading = false;\n/**\n * Handle action\n * @param {TinyMCE} editor\n */\nexport const handleAction = async(editor) => {\n if (isLoading) {\n return;\n }\n if (modal === null) {\n isLoading = true;\n modal = await createDialogue();\n isLoading = false;\n }\n\n // Issue, editor var does not get updated\n // Bind save action to the correct editor\n const $btn = modal.footer.find(\"button.btn[data-action]\");\n $btn.off(\"click.codepro\").on(\"click.codepro\", (evt) => {\n if (evt.target.classList.contains(\"btn-primary\")) {\n // eslint-disable-next-line camelcase\n const updatedCode = codeEditorInstance?.getValue({source_view: true});\n editor.setContent(updatedCode ?? '');\n }\n modal.hide();\n // Delete content\n codeEditorInstance?.setValue();\n });\n\n // Insert caret marker and retrieve html code to pass to CodeMirror\n const markerNode = document.createElement(\"SPAN\");\n markerNode.innerHTML = ' ';\n markerNode.classList.add('CmCaReT');\n const currentNode = editor.selection.getStart();\n currentNode.append(markerNode);\n // eslint-disable-next-line camelcase\n let html = editor.getContent({source_view: true});\n html = html.replace(/]*)>([^<]*)<\\/span>/gm, String.fromCharCode(0));\n markerNode.remove();\n\n if (getPref(\"prettify\")) {\n html = codeEditorInstance?.prettifyCode(html);\n }\n codeEditorInstance?.setValue(html);\n\n modal.show();\n setTimeout(() => codeEditorInstance?.focus(), 500);\n};\n\n/**\n * Loads cm6 on demand (The first load will be delayed a little bit)\n * @returns {Promise}\n */\nconst requireCm6Pro = () => {\n return new Promise((resolve) => {\n require(['tiny_codepro/cm6pro-lazy'], (CodeProEditor) => {\n resolve(CodeProEditor);\n });\n });\n};\n\n/**\n * Returns the modal instance\n * @returns {Promise}\n */\nconst createDialogue = async() => {\n const data = {\n elementid: Math.random().toString(32).substring(2)\n };\n\n // Show modal with buttons.\n const modal = await createModal({\n templateContext: data\n });\n\n modal.getRoot().find(\".modal-dialog.modal-lg\").addClass(\"tiny_codepro-dlg\");\n // Disable keyboard events (ESC key) on this modal\n modal.getRoot().off('keydown');\n // Prevent modal from closing on outside clicks\n modal.getRoot().on(ModalEvents.outsideClick, (evt) => {\n evt.preventDefault();\n });\n modal.body.css(\"overflow-y\", \"overlay\");\n // Override styles imposed by body.tox-fullscreen on modals\n modal.header.css('height', '61.46px');\n modal.header.css('padding', '1rem 1rem');\n\n const CodeProEditor = await requireCm6Pro();\n const targetElem = modal.body.find('.tiny_codepro-editor-area')[0];\n codeEditorInstance = new CodeProEditor(targetElem);\n\n modal.footer.find(\"button.btn.btn-light\").on(\"click\", (evt) => {\n evt.preventDefault();\n const ds = evt.currentTarget.dataset;\n const icon = evt.currentTarget.querySelector(\"i.fa\");\n const $dlgElem = modal.getRoot().find(dialogQuery);\n if (ds.fs) {\n if (ds.fs === \"false\") {\n // Set fullscreen mode\n ds.fs = \"true\";\n modal.header.hide();\n $dlgElem.removeClass(\"modal-dialog modal-lg modal-dialog-scrollable\");\n $dlgElem.addClass(\"tiny_codepro-fullscreen\");\n } else {\n // Set to modal-lg\n ds.fs = \"false\";\n modal.header.show();\n $dlgElem.removeClass(\"tiny_codepro-fullscreen\");\n $dlgElem.addClass(\"modal-dialog modal-lg modal-dialog-scrollable\");\n }\n setPref(\"fs\", ds.fs, true);\n } else if (ds.theme) {\n if (ds.theme === \"light\") {\n ds.theme = \"dark\";\n codeEditorInstance.setTheme(\"dark\");\n $dlgElem.addClass(\"tiny_codepro-dark\");\n } else {\n ds.theme = \"light\";\n codeEditorInstance.setTheme(\"light\");\n $dlgElem.removeClass(\"tiny_codepro-dark\");\n }\n toggleClasses(icon, [\"fa-sun-o\", \"fa-moon-o\"]);\n setPref(\"theme\", ds.theme, true);\n } else if (ds.wrap) {\n if (ds.wrap === \"true\") {\n ds.wrap = false;\n codeEditorInstance?.setLineWrapping(false);\n } else {\n ds.wrap = true;\n codeEditorInstance?.setLineWrapping(true);\n }\n setPref(\"wrap\", ds.wrap, true);\n toggleClasses(icon, [\"fa-exchange\", \"fa-long-arrow-right\"]);\n } else if (ds.prettify !== undefined) {\n codeEditorInstance?.prettify();\n } else if (ds.autoPrettify !== undefined) {\n setPref(\"prettify\", !getPref(\"prettify\", false), true);\n const icon = evt.currentTarget.querySelector(\"i\");\n toggleClasses(icon, [\"fa-times\", \"fa-check\"]);\n }\n });\n\n modal.getRoot().on(ModalEvents.hidden, () => {\n codeEditorInstance?.setValue();\n });\n\n // Setting stored preferences\n const currentTheme = getPref(\"theme\", \"light\");\n const currentWrap = getPref(\"wrap\", \"false\");\n const currentFs = getPref(\"fs\", \"false\");\n const currentPrettify = getPref(\"prettify\", false);\n\n if (currentTheme !== \"light\") {\n modal.footer.find(\"button.btn.btn-light[data-theme]\").click();\n }\n if (currentWrap === \"true\") {\n modal.footer.find(\"button.btn.btn-light[data-wrap]\").click();\n }\n if (currentFs === \"true\") {\n modal.footer.find(\"button.btn.btn-light[data-fs]\").click();\n }\n if (currentPrettify) {\n modal.footer.find(\"button.btn.btn-light[data-auto-prettify] > i\")\n .removeClass(\"fa-times\")\n .addClass(\"fa-check\");\n }\n return modal;\n};"],"names":["modal","codeEditorInstance","toggleClasses","el","classList","cl","forEach","className","toggle","isLoading","async","createDialogue","footer","find","off","on","evt","target","contains","updatedCode","_codeEditorInstance","getValue","source_view","editor","setContent","hide","setValue","markerNode","document","createElement","innerHTML","add","selection","getStart","append","html","getContent","replace","String","fromCharCode","remove","_codeEditorInstance3","prettifyCode","show","setTimeout","_codeEditorInstance5","focus","data","elementid","Math","random","toString","substring","templateContext","getRoot","addClass","ModalEvents","outsideClick","preventDefault","body","css","header","CodeProEditor","Promise","resolve","require","targetElem","ds","currentTarget","dataset","icon","querySelector","$dlgElem","fs","removeClass","theme","setTheme","wrap","setLineWrapping","undefined","prettify","autoPrettify","hidden","currentTheme","currentWrap","currentFs","currentPrettify","click"],"mappings":"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"}
\ No newline at end of file
diff --git a/amd/src/commands.js b/amd/src/commands.js
index b4ff71d..f63fe8f 100644
--- a/amd/src/commands.js
+++ b/amd/src/commands.js
@@ -47,13 +47,7 @@ export const getSetup = async() => {
editor.ui.registry.addButton(component, {
icon,
tooltip: pluginName,
- onAction: () => handleAction(editor),
- enabled: false,
- onSetup: (api) => {
- const cb = () => api.setEnabled(true);
- editor.on('SetContent', cb);
- return () => editor.off('SetContent', cb);
- }
+ onAction: () => handleAction(editor)
});
// Add the Menu Item.
diff --git a/amd/src/plugin.js b/amd/src/plugin.js
index c2e484b..6894214 100644
--- a/amd/src/plugin.js
+++ b/amd/src/plugin.js
@@ -48,9 +48,12 @@ export default new Promise(async(resolve) => {
// Register options.
registerOptions(editor);
// Resolve the Plugin and include configuration.
- // Setup commands.
- setupCommands(editor);
+ // Setup commands (only if the content has been set) to prevent from opening the modal without content.
+ editor.once('SetContent', () => {
+ setupCommands(editor);
+ });
return pluginMetadata;
});
+
resolve([pluginName, Configuration]);
});
diff --git a/amd/src/ui.js b/amd/src/ui.js
index 4814b3b..3b664be 100644
--- a/amd/src/ui.js
+++ b/amd/src/ui.js
@@ -40,13 +40,19 @@ const toggleClasses = function(el, classList) {
});
};
+let isLoading = false;
/**
* Handle action
* @param {TinyMCE} editor
*/
export const handleAction = async(editor) => {
+ if (isLoading) {
+ return;
+ }
if (modal === null) {
- await createDialogue();
+ isLoading = true;
+ modal = await createDialogue();
+ isLoading = false;
}
// Issue, editor var does not get updated
@@ -55,12 +61,12 @@ export const handleAction = async(editor) => {
$btn.off("click.codepro").on("click.codepro", (evt) => {
if (evt.target.classList.contains("btn-primary")) {
// eslint-disable-next-line camelcase
- const updatedCode = codeEditorInstance.getValue({source_view: true});
- editor.setContent(updatedCode);
+ const updatedCode = codeEditorInstance?.getValue({source_view: true});
+ editor.setContent(updatedCode ?? '');
}
modal.hide();
// Delete content
- codeEditorInstance.setValue();
+ codeEditorInstance?.setValue();
});
// Insert caret marker and retrieve html code to pass to CodeMirror
@@ -75,21 +81,37 @@ export const handleAction = async(editor) => {
markerNode.remove();
if (getPref("prettify")) {
- html = codeEditorInstance.prettifyCode(html);
+ html = codeEditorInstance?.prettifyCode(html);
}
- codeEditorInstance.setValue(html);
+ codeEditorInstance?.setValue(html);
modal.show();
- setTimeout(() => codeEditorInstance.focus(), 500);
+ setTimeout(() => codeEditorInstance?.focus(), 500);
};
+/**
+ * Loads cm6 on demand (The first load will be delayed a little bit)
+ * @returns {Promise}
+ */
+const requireCm6Pro = () => {
+ return new Promise((resolve) => {
+ require(['tiny_codepro/cm6pro-lazy'], (CodeProEditor) => {
+ resolve(CodeProEditor);
+ });
+ });
+};
+
+/**
+ * Returns the modal instance
+ * @returns {Promise}
+ */
const createDialogue = async() => {
const data = {
elementid: Math.random().toString(32).substring(2)
};
// Show modal with buttons.
- modal = await createModal({
+ const modal = await createModal({
templateContext: data
});
@@ -105,89 +127,84 @@ const createDialogue = async() => {
modal.header.css('height', '61.46px');
modal.header.css('padding', '1rem 1rem');
- return new Promise((resolve) => {
- // Load cm6 on demand
- require(['tiny_codepro/cm6pro-lazy'], (CodeProEditor) => {
- const targetElem = modal.body.find('.tiny_codepro-editor-area')[0];
- codeEditorInstance = new CodeProEditor(targetElem);
-
- modal.footer.find("button.btn.btn-light").on("click", (evt) => {
- evt.preventDefault();
- const ds = evt.currentTarget.dataset;
- const icon = evt.currentTarget.querySelector("i.fa");
- const $dlgElem = modal.getRoot().find(dialogQuery);
- if (ds.fs) {
- if (ds.fs === "false") {
- // Set fullscreen mode
- ds.fs = "true";
- modal.header.hide();
- $dlgElem.removeClass("modal-dialog modal-lg modal-dialog-scrollable");
- $dlgElem.addClass("tiny_codepro-fullscreen");
- } else {
- // Set to modal-lg
- ds.fs = "false";
- modal.header.show();
- $dlgElem.removeClass("tiny_codepro-fullscreen");
- $dlgElem.addClass("modal-dialog modal-lg modal-dialog-scrollable");
- }
- setPref("fs", ds.fs, true);
- } else if (ds.theme) {
- if (ds.theme === "light") {
- ds.theme = "dark";
- codeEditorInstance.setTheme("dark");
- $dlgElem.addClass("tiny_codepro-dark");
- } else {
- ds.theme = "light";
- codeEditorInstance.setTheme("light");
- $dlgElem.removeClass("tiny_codepro-dark");
- }
- toggleClasses(icon, ["fa-sun-o", "fa-moon-o"]);
- setPref("theme", ds.theme, true);
- } else if (ds.wrap) {
- if (ds.wrap === "true") {
- ds.wrap = false;
- codeEditorInstance.setLineWrapping(false);
- } else {
- ds.wrap = true;
- codeEditorInstance.setLineWrapping(true);
- }
- setPref("wrap", ds.wrap, true);
- toggleClasses(icon, ["fa-exchange", "fa-long-arrow-right"]);
- } else if (ds.prettify !== undefined) {
- codeEditorInstance.prettify();
- } else if (ds.autoPrettify !== undefined) {
- setPref("prettify", !getPref("prettify", false), true);
- const icon = evt.currentTarget.querySelector("i");
- toggleClasses(icon, ["fa-times", "fa-check"]);
- }
- });
-
- modal.getRoot().on(ModalEvents.hidden, () => {
- codeEditorInstance.setValue();
- });
-
- // Setting stored preferences
- const currentTheme = getPref("theme", "light");
- const currentWrap = getPref("wrap", "false");
- const currentFs = getPref("fs", "false");
- const currentPrettify = getPref("prettify", false);
-
- if (currentTheme !== "light") {
- modal.footer.find("button.btn.btn-light[data-theme]").click();
- }
- if (currentWrap === "true") {
- modal.footer.find("button.btn.btn-light[data-wrap]").click();
+ const CodeProEditor = await requireCm6Pro();
+ const targetElem = modal.body.find('.tiny_codepro-editor-area')[0];
+ codeEditorInstance = new CodeProEditor(targetElem);
+
+ modal.footer.find("button.btn.btn-light").on("click", (evt) => {
+ evt.preventDefault();
+ const ds = evt.currentTarget.dataset;
+ const icon = evt.currentTarget.querySelector("i.fa");
+ const $dlgElem = modal.getRoot().find(dialogQuery);
+ if (ds.fs) {
+ if (ds.fs === "false") {
+ // Set fullscreen mode
+ ds.fs = "true";
+ modal.header.hide();
+ $dlgElem.removeClass("modal-dialog modal-lg modal-dialog-scrollable");
+ $dlgElem.addClass("tiny_codepro-fullscreen");
+ } else {
+ // Set to modal-lg
+ ds.fs = "false";
+ modal.header.show();
+ $dlgElem.removeClass("tiny_codepro-fullscreen");
+ $dlgElem.addClass("modal-dialog modal-lg modal-dialog-scrollable");
}
- if (currentFs === "true") {
- modal.footer.find("button.btn.btn-light[data-fs]").click();
+ setPref("fs", ds.fs, true);
+ } else if (ds.theme) {
+ if (ds.theme === "light") {
+ ds.theme = "dark";
+ codeEditorInstance.setTheme("dark");
+ $dlgElem.addClass("tiny_codepro-dark");
+ } else {
+ ds.theme = "light";
+ codeEditorInstance.setTheme("light");
+ $dlgElem.removeClass("tiny_codepro-dark");
}
- if (currentPrettify) {
- modal.footer.find("button.btn.btn-light[data-auto-prettify] > i")
- .removeClass("fa-times")
- .addClass("fa-check");
+ toggleClasses(icon, ["fa-sun-o", "fa-moon-o"]);
+ setPref("theme", ds.theme, true);
+ } else if (ds.wrap) {
+ if (ds.wrap === "true") {
+ ds.wrap = false;
+ codeEditorInstance?.setLineWrapping(false);
+ } else {
+ ds.wrap = true;
+ codeEditorInstance?.setLineWrapping(true);
}
+ setPref("wrap", ds.wrap, true);
+ toggleClasses(icon, ["fa-exchange", "fa-long-arrow-right"]);
+ } else if (ds.prettify !== undefined) {
+ codeEditorInstance?.prettify();
+ } else if (ds.autoPrettify !== undefined) {
+ setPref("prettify", !getPref("prettify", false), true);
+ const icon = evt.currentTarget.querySelector("i");
+ toggleClasses(icon, ["fa-times", "fa-check"]);
+ }
+ });
- resolve(modal);
- });
+ modal.getRoot().on(ModalEvents.hidden, () => {
+ codeEditorInstance?.setValue();
});
+
+ // Setting stored preferences
+ const currentTheme = getPref("theme", "light");
+ const currentWrap = getPref("wrap", "false");
+ const currentFs = getPref("fs", "false");
+ const currentPrettify = getPref("prettify", false);
+
+ if (currentTheme !== "light") {
+ modal.footer.find("button.btn.btn-light[data-theme]").click();
+ }
+ if (currentWrap === "true") {
+ modal.footer.find("button.btn.btn-light[data-wrap]").click();
+ }
+ if (currentFs === "true") {
+ modal.footer.find("button.btn.btn-light[data-fs]").click();
+ }
+ if (currentPrettify) {
+ modal.footer.find("button.btn.btn-light[data-auto-prettify] > i")
+ .removeClass("fa-times")
+ .addClass("fa-check");
+ }
+ return modal;
};
\ No newline at end of file