diff --git a/lib/editor/tiny/plugins/premium/amd/build/common.min.js b/lib/editor/tiny/plugins/premium/amd/build/common.min.js new file mode 100644 index 00000000000..959a0b8c8e4 --- /dev/null +++ b/lib/editor/tiny/plugins/premium/amd/build/common.min.js @@ -0,0 +1,3 @@ +define("tiny_premium/common",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;return _exports.default={pluginName:"tiny_premium/plugin",component:"tiny_premium"},_exports.default})); + +//# sourceMappingURL=common.min.js.map \ No newline at end of file diff --git a/lib/editor/tiny/plugins/premium/amd/build/common.min.js.map b/lib/editor/tiny/plugins/premium/amd/build/common.min.js.map new file mode 100644 index 00000000000..8ad877fb412 --- /dev/null +++ b/lib/editor/tiny/plugins/premium/amd/build/common.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"common.min.js","sources":["../src/common.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 Premium common values.\n *\n * @module tiny_premium/common\n * @copyright 2023 David Woloszyn \n * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nexport default {\n pluginName: 'tiny_premium/plugin',\n component: 'tiny_premium',\n};\n"],"names":["pluginName","component"],"mappings":"qKAuBe,CACXA,WAAY,sBACZC,UAAW"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/premium/amd/build/configuration.min.js b/lib/editor/tiny/plugins/premium/amd/build/configuration.min.js new file mode 100644 index 00000000000..621fad27a73 --- /dev/null +++ b/lib/editor/tiny/plugins/premium/amd/build/configuration.min.js @@ -0,0 +1,3 @@ +define("tiny_premium/configuration",["exports","editor_tiny/utils"],(function(_exports,_utils){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.configure=void 0;_exports.configure=instanceConfig=>{let plugins=instanceConfig.plugins,menu=instanceConfig.menu,toolbar=(toolbar=>(toolbar=(0,_utils.addToolbarSection)(toolbar,"premium_a","advanced",!0),(0,_utils.addToolbarSection)(toolbar,"premium_b","formatting",!0)))(instanceConfig.toolbar),contextmenu=instanceConfig.contextmenu;return plugins+=" advtable",menu=(0,_utils.addMenubarItem)(menu,"table","| advtablerownumbering","advtablesort"),plugins+=" editimage",toolbar=(0,_utils.addToolbarButton)(toolbar,"content","editimage","tiny_media_image"),instanceConfig.editimage_toolbar="rotateleft rotateright flipv fliph editimage",plugins+=" export",menu=(0,_utils.addMenubarItem)(menu,"tools","| export"),plugins+=" pageembed",toolbar=(0,_utils.addToolbarButton)(toolbar,"content","pageembed","tiny_media_video"),plugins+=" typography",toolbar=(0,_utils.addToolbarButton)(toolbar,"premium_b","typography"),plugins+=" casechange",toolbar=(0,_utils.addToolbarButton)(toolbar,"premium_a","casechange"),plugins+=" checklist",toolbar=(0,_utils.addToolbarButton)(toolbar,"lists","checklist"),plugins+=" tinymcespellchecker",menu=(0,_utils.addMenubarItem)(menu,"tools","spellcheckdialog","spellcheckerlanguage"),contextmenu=(0,_utils.addContextmenuItem)(contextmenu,"spellchecker"),toolbar=(0,_utils.addToolbarButton)(toolbar,"premium_a","spellcheckdialog"),plugins+=" autocorrect",menu=(0,_utils.addMenubarItem)(menu,"tools","| autocorrect capitalization","spellcheckdialog"),plugins+=" permanentpen",menu=(0,_utils.addMenubarItem)(menu,"format","| permanentpen configurepermanentpen"),toolbar=(0,_utils.addToolbarButton)(toolbar,"premium_a","permanentpen"),contextmenu=(0,_utils.addContextmenuItem)(contextmenu,"configurepermanentpen"),plugins+=" formatpainter",toolbar=(0,_utils.addToolbarButton)(toolbar,"premium_a","formatpainter"),plugins+=" linkchecker",contextmenu=(0,_utils.addContextmenuItem)(contextmenu,"linkchecker"),plugins+=" tableofcontents",toolbar=(0,_utils.addToolbarButton)(toolbar,"premium_a","tableofcontents"),plugins+=" footnotes",toolbar=(0,_utils.addToolbarButton)(toolbar,"premium_a","footnotes"),menu=(0,_utils.addMenubarItem)(menu,"insert","footnotes","tableofcontents"),plugins+=" powerpaste",{plugins:plugins,toolbar:toolbar,menu:menu,contextmenu:contextmenu}}})); + +//# sourceMappingURL=configuration.min.js.map \ No newline at end of file diff --git a/lib/editor/tiny/plugins/premium/amd/build/configuration.min.js.map b/lib/editor/tiny/plugins/premium/amd/build/configuration.min.js.map new file mode 100644 index 00000000000..ca798b5a1b9 --- /dev/null +++ b/lib/editor/tiny/plugins/premium/amd/build/configuration.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"configuration.min.js","sources":["../src/configuration.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 Premium configuration.\n *\n * @module tiny_premium/configuration\n * @copyright 2023 David Woloszyn \n * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {\n addToolbarButton,\n addMenubarItem,\n addToolbarSection,\n addContextmenuItem\n} from 'editor_tiny/utils';\n\nconst configureToolbar = (toolbar) => {\n // Add premium toolbar sections to house all the plugins with no natural home.\n toolbar = addToolbarSection(toolbar, 'premium_a', 'advanced', true);\n toolbar = addToolbarSection(toolbar, 'premium_b', 'formatting', true);\n return toolbar;\n};\n\nexport const configure = (instanceConfig) => {\n // There is some manipulating of the plugin menu, toolbar, context and quickbar items.\n // This was necessary to enhance user experience and closer align to the Tiny demo site.\n let plugins = instanceConfig.plugins;\n let menu = instanceConfig.menu;\n let toolbar = configureToolbar(instanceConfig.toolbar);\n let contextmenu = instanceConfig.contextmenu;\n let pluginsettings = {};\n\n // Advanced Table.\n plugins += ` advtable`;\n menu = addMenubarItem(menu, 'table', '| advtablerownumbering', 'advtablesort');\n\n // Enhanced Image Editing.\n plugins += ` editimage`;\n toolbar = addToolbarButton(toolbar, 'content', 'editimage', 'tiny_media_image');\n // Remove the duplicate image button from the quickbar toolbar by redefining the values without 'imageoptions'.\n // eslint-disable-next-line camelcase\n instanceConfig.editimage_toolbar = 'rotateleft rotateright flipv fliph editimage';\n\n // Export.\n plugins += ` export`;\n menu = addMenubarItem(menu, 'tools', '| export');\n\n // Page Embed.\n plugins += ` pageembed`;\n toolbar = addToolbarButton(toolbar, 'content', 'pageembed', 'tiny_media_video');\n\n // Advanced Typography.\n plugins += ` typography`;\n toolbar = addToolbarButton(toolbar, 'premium_b', 'typography');\n\n // Case Change.\n plugins += ` casechange`;\n toolbar = addToolbarButton(toolbar, 'premium_a', 'casechange');\n\n // Checklist.\n plugins += ` checklist`;\n toolbar = addToolbarButton(toolbar, 'lists', 'checklist');\n\n // Spell Checker Pro.\n plugins += ` tinymcespellchecker`;\n menu = addMenubarItem(menu, 'tools', 'spellcheckdialog', 'spellcheckerlanguage');\n contextmenu = addContextmenuItem(contextmenu, 'spellchecker');\n toolbar = addToolbarButton(toolbar, 'premium_a', 'spellcheckdialog');\n\n // Spelling Autocorrect.\n plugins += ` autocorrect`;\n menu = addMenubarItem(menu, 'tools', '| autocorrect capitalization', 'spellcheckdialog');\n\n // Permanent Pen.\n plugins += ` permanentpen`;\n menu = addMenubarItem(menu, 'format', '| permanentpen configurepermanentpen');\n toolbar = addToolbarButton(toolbar, 'premium_a', 'permanentpen');\n contextmenu = addContextmenuItem(contextmenu, 'configurepermanentpen');\n\n // Format Painter.\n plugins += ` formatpainter`;\n toolbar = addToolbarButton(toolbar, 'premium_a', 'formatpainter');\n\n // Link Checker.\n plugins += ` linkchecker`;\n contextmenu = addContextmenuItem(contextmenu, 'linkchecker');\n\n // Table of Contents.\n plugins += ` tableofcontents`;\n toolbar = addToolbarButton(toolbar, 'premium_a', 'tableofcontents');\n\n // Footnotes.\n plugins += ` footnotes`;\n toolbar = addToolbarButton(toolbar, 'premium_a', 'footnotes');\n menu = addMenubarItem(menu, 'insert', 'footnotes', 'tableofcontents');\n\n // Powerpaste.\n plugins += ` powerpaste`;\n\n return {\n plugins,\n toolbar,\n menu,\n contextmenu,\n ...pluginsettings\n };\n};\n"],"names":["instanceConfig","plugins","menu","toolbar","configureToolbar","contextmenu","editimage_toolbar"],"mappings":"oMAqC0BA,qBAGlBC,QAAUD,eAAeC,QACzBC,KAAOF,eAAeE,KACtBC,QAZkBA,CAAAA,UAEtBA,SAAU,4BAAkBA,QAAS,YAAa,YAAY,IACpD,4BAAkBA,QAAS,YAAa,cAAc,IASlDC,CAAiBJ,eAAeG,SAC1CE,YAAcL,eAAeK,mBAIjCJ,qBACAC,MAAO,yBAAeA,KAAM,QAAS,yBAA0B,gBAG/DD,sBACAE,SAAU,2BAAiBA,QAAS,UAAW,YAAa,oBAG5DH,eAAeM,kBAAoB,+CAGnCL,mBACAC,MAAO,yBAAeA,KAAM,QAAS,YAGrCD,sBACAE,SAAU,2BAAiBA,QAAS,UAAW,YAAa,oBAG5DF,uBACAE,SAAU,2BAAiBA,QAAS,YAAa,cAGjDF,uBACAE,SAAU,2BAAiBA,QAAS,YAAa,cAGjDF,sBACAE,SAAU,2BAAiBA,QAAS,QAAS,aAG7CF,gCACAC,MAAO,yBAAeA,KAAM,QAAS,mBAAoB,wBACzDG,aAAc,6BAAmBA,YAAa,gBAC9CF,SAAU,2BAAiBA,QAAS,YAAa,oBAGjDF,wBACAC,MAAO,yBAAeA,KAAM,QAAS,+BAAgC,oBAGrED,yBACAC,MAAO,yBAAeA,KAAM,SAAU,wCACtCC,SAAU,2BAAiBA,QAAS,YAAa,gBACjDE,aAAc,6BAAmBA,YAAa,yBAG9CJ,0BACAE,SAAU,2BAAiBA,QAAS,YAAa,iBAGjDF,wBACAI,aAAc,6BAAmBA,YAAa,eAG9CJ,4BACAE,SAAU,2BAAiBA,QAAS,YAAa,mBAGjDF,sBACAE,SAAU,2BAAiBA,QAAS,YAAa,aACjDD,MAAO,yBAAeA,KAAM,SAAU,YAAa,mBAGnDD,uBAEO,CACHA,QAAAA,QACAE,QAAAA,QACAD,KAAAA,KACAG,YAAAA"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/premium/amd/build/external.min.js b/lib/editor/tiny/plugins/premium/amd/build/external.min.js new file mode 100644 index 00000000000..f23d5c14110 --- /dev/null +++ b/lib/editor/tiny/plugins/premium/amd/build/external.min.js @@ -0,0 +1,10 @@ +define("tiny_premium/external",["exports","core/ajax"],(function(_exports,_ajax){var obj; +/** + * Helper to get external content for Tiny Premium plugin. + * + * @module tiny_premium/external + * @copyright 2023 David Woloszyn + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.getApiKey=void 0,_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};_exports.getApiKey=contextId=>{const request={methodname:"tiny_premium_get_api_key",args:{contextid:contextId}};return _ajax.default.call([request])[0]}})); + +//# sourceMappingURL=external.min.js.map \ No newline at end of file diff --git a/lib/editor/tiny/plugins/premium/amd/build/external.min.js.map b/lib/editor/tiny/plugins/premium/amd/build/external.min.js.map new file mode 100644 index 00000000000..057c665ccb7 --- /dev/null +++ b/lib/editor/tiny/plugins/premium/amd/build/external.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"external.min.js","sources":["../src/external.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 * Helper to get external content for Tiny Premium plugin.\n *\n * @module tiny_premium/external\n * @copyright 2023 David Woloszyn \n * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n/**\n * Due to the order items are initialise, options.js will not work in getting the API key.\n * This external method is used to get the API key in time.\n *\n * @param {Number} contextId The context id\n * @return {Promise}\n */\nexport const getApiKey = (contextId) => {\n const request = {\n methodname: 'tiny_premium_get_api_key',\n args: {\n contextid: contextId\n }\n };\n return Ajax.call([request])[0];\n};\n"],"names":["contextId","request","methodname","args","contextid","Ajax","call"],"mappings":";;;;;;;8JAgC0BA,kBAChBC,QAAU,CACZC,WAAY,2BACZC,KAAM,CACFC,UAAWJ,mBAGZK,cAAKC,KAAK,CAACL,UAAU"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/premium/amd/build/plugin.min.js b/lib/editor/tiny/plugins/premium/amd/build/plugin.min.js new file mode 100644 index 00000000000..cb93b76838a --- /dev/null +++ b/lib/editor/tiny/plugins/premium/amd/build/plugin.min.js @@ -0,0 +1,10 @@ +define("tiny_premium/plugin",["exports","editor_tiny/loader","editor_tiny/utils","tiny_premium/common","tiny_premium/configuration","tiny_premium/external","core/config"],(function(_exports,_loader,_utils,_common,Configuration,_external,_config){var obj;function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,Configuration=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj} +/** + * Tiny Premium plugin for Moodle. + * + * @module tiny_premium/plugin + * @copyright 2023 David Woloszyn + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */(Configuration);const currentContextId=(_config=(obj=_config)&&obj.__esModule?obj:{default:obj}).default.contextid;var _default=new Promise((async resolve=>{const[tinyMCE,pluginMetadata,externalData]=await Promise.all([(0,_loader.getTinyMCE)(),(0,_utils.getPluginMetadata)(_common.component,_common.pluginName),(0,_external.getApiKey)(currentContextId)]);tinyMCE.PluginManager.add("".concat(_common.component,"/plugin"),(()=>pluginMetadata)),await getTinyPremium(externalData.apikey),resolve(["".concat(_common.component,"/plugin"),Configuration])}));let tinyPremiumPromise;_exports.default=_default;const getTinyPremium=apikey=>tinyPremiumPromise||(tinyPremiumPromise=new Promise(((resolve,reject)=>{const head=document.querySelector("head"),script=document.createElement("script");script.dataset.tinymce="premium",script.src="https://cdn.tiny.cloud/1/".concat(apikey,"/tinymce/6/plugins.min.js"),script.referrerpolicy="origin",script.addEventListener("load",(()=>{resolve()}),!1),script.addEventListener("error",(err=>{reject(err)}),!1),head.append(script)})),tinyPremiumPromise);return _exports.default})); + +//# sourceMappingURL=plugin.min.js.map \ No newline at end of file diff --git a/lib/editor/tiny/plugins/premium/amd/build/plugin.min.js.map b/lib/editor/tiny/plugins/premium/amd/build/plugin.min.js.map new file mode 100644 index 00000000000..f0fa0b24920 --- /dev/null +++ b/lib/editor/tiny/plugins/premium/amd/build/plugin.min.js.map @@ -0,0 +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 Premium plugin for Moodle.\n *\n * @module tiny_premium/plugin\n * @copyright 2023 David Woloszyn \n * @license https://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';\nimport {component, pluginName} from 'tiny_premium/common';\nimport * as Configuration from 'tiny_premium/configuration';\nimport {getApiKey} from 'tiny_premium/external';\nimport Config from 'core/config';\n\nconst currentContextId = Config.contextid;\n\n// eslint-disable-next-line no-async-promise-executor\nexport default new Promise(async(resolve) => {\n const [\n tinyMCE,\n pluginMetadata,\n externalData\n ] = await Promise.all([\n getTinyMCE(),\n getPluginMetadata(component, pluginName),\n getApiKey(currentContextId)\n ]);\n\n tinyMCE.PluginManager.add(`${component}/plugin`, () => {\n return pluginMetadata;\n });\n\n // Load the Tiny Premium script using the provided API key.\n await getTinyPremium(externalData.apikey);\n\n resolve([`${component}/plugin`, Configuration]);\n});\n\nlet tinyPremiumPromise;\n\n/**\n * Promise for Tiny Premium plugins script.\n *\n * @param {string} apikey\n * @return {Promise}\n */\nconst getTinyPremium = (apikey) => {\n if (tinyPremiumPromise) {\n return tinyPremiumPromise;\n }\n\n tinyPremiumPromise = new Promise((resolve, reject) => {\n const head = document.querySelector('head');\n const script = document.createElement('script');\n script.dataset.tinymce = 'premium';\n script.src = `https://cdn.tiny.cloud/1/${apikey}/tinymce/6/plugins.min.js`;\n script.referrerpolicy = \"origin\";\n\n script.addEventListener('load', () => {\n resolve();\n }, false);\n\n script.addEventListener('error', (err) => {\n reject(err);\n }, false);\n\n head.append(script);\n });\n\n return tinyPremiumPromise;\n};\n"],"names":["currentContextId","contextid","Promise","async","tinyMCE","pluginMetadata","externalData","all","component","pluginName","PluginManager","add","getTinyPremium","apikey","resolve","Configuration","tinyPremiumPromise","reject","head","document","querySelector","script","createElement","dataset","tinymce","src","referrerpolicy","addEventListener","err","append"],"mappings":";;;;;;;2BA8BMA,mFAA0BC,uBAGjB,IAAIC,SAAQC,MAAAA,gBAEnBC,QACAC,eACAC,oBACMJ,QAAQK,IAAI,EAClB,yBACA,4BAAkBC,kBAAWC,qBAC7B,uBAAUT,oBAGdI,QAAQM,cAAcC,cAAOH,8BAAoB,IACtCH,uBAILO,eAAeN,aAAaO,QAElCC,QAAQ,WAAIN,6BAAoBO,uBAGhCC,mDAQEJ,eAAkBC,QAChBG,qBAIJA,mBAAqB,IAAId,SAAQ,CAACY,QAASG,gBACjCC,KAAOC,SAASC,cAAc,QAC9BC,OAASF,SAASG,cAAc,UACtCD,OAAOE,QAAQC,QAAU,UACzBH,OAAOI,uCAAkCZ,oCACzCQ,OAAOK,eAAiB,SAExBL,OAAOM,iBAAiB,QAAQ,KAC5Bb,aACD,GAEHO,OAAOM,iBAAiB,SAAUC,MAC9BX,OAAOW,QACR,GAEHV,KAAKW,OAAOR,WAGTL"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/premium/amd/src/common.js b/lib/editor/tiny/plugins/premium/amd/src/common.js new file mode 100644 index 00000000000..3ee35d20c5f --- /dev/null +++ b/lib/editor/tiny/plugins/premium/amd/src/common.js @@ -0,0 +1,27 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Tiny Premium common values. + * + * @module tiny_premium/common + * @copyright 2023 David Woloszyn + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +export default { + pluginName: 'tiny_premium/plugin', + component: 'tiny_premium', +}; diff --git a/lib/editor/tiny/plugins/premium/amd/src/configuration.js b/lib/editor/tiny/plugins/premium/amd/src/configuration.js new file mode 100644 index 00000000000..1b2cfa7e14c --- /dev/null +++ b/lib/editor/tiny/plugins/premium/amd/src/configuration.js @@ -0,0 +1,121 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Tiny Premium configuration. + * + * @module tiny_premium/configuration + * @copyright 2023 David Woloszyn + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import { + addToolbarButton, + addMenubarItem, + addToolbarSection, + addContextmenuItem +} from 'editor_tiny/utils'; + +const configureToolbar = (toolbar) => { + // Add premium toolbar sections to house all the plugins with no natural home. + toolbar = addToolbarSection(toolbar, 'premium_a', 'advanced', true); + toolbar = addToolbarSection(toolbar, 'premium_b', 'formatting', true); + return toolbar; +}; + +export const configure = (instanceConfig) => { + // There is some manipulating of the plugin menu, toolbar, context and quickbar items. + // This was necessary to enhance user experience and closer align to the Tiny demo site. + let plugins = instanceConfig.plugins; + let menu = instanceConfig.menu; + let toolbar = configureToolbar(instanceConfig.toolbar); + let contextmenu = instanceConfig.contextmenu; + let pluginsettings = {}; + + // Advanced Table. + plugins += ` advtable`; + menu = addMenubarItem(menu, 'table', '| advtablerownumbering', 'advtablesort'); + + // Enhanced Image Editing. + plugins += ` editimage`; + toolbar = addToolbarButton(toolbar, 'content', 'editimage', 'tiny_media_image'); + // Remove the duplicate image button from the quickbar toolbar by redefining the values without 'imageoptions'. + // eslint-disable-next-line camelcase + instanceConfig.editimage_toolbar = 'rotateleft rotateright flipv fliph editimage'; + + // Export. + plugins += ` export`; + menu = addMenubarItem(menu, 'tools', '| export'); + + // Page Embed. + plugins += ` pageembed`; + toolbar = addToolbarButton(toolbar, 'content', 'pageembed', 'tiny_media_video'); + + // Advanced Typography. + plugins += ` typography`; + toolbar = addToolbarButton(toolbar, 'premium_b', 'typography'); + + // Case Change. + plugins += ` casechange`; + toolbar = addToolbarButton(toolbar, 'premium_a', 'casechange'); + + // Checklist. + plugins += ` checklist`; + toolbar = addToolbarButton(toolbar, 'lists', 'checklist'); + + // Spell Checker Pro. + plugins += ` tinymcespellchecker`; + menu = addMenubarItem(menu, 'tools', 'spellcheckdialog', 'spellcheckerlanguage'); + contextmenu = addContextmenuItem(contextmenu, 'spellchecker'); + toolbar = addToolbarButton(toolbar, 'premium_a', 'spellcheckdialog'); + + // Spelling Autocorrect. + plugins += ` autocorrect`; + menu = addMenubarItem(menu, 'tools', '| autocorrect capitalization', 'spellcheckdialog'); + + // Permanent Pen. + plugins += ` permanentpen`; + menu = addMenubarItem(menu, 'format', '| permanentpen configurepermanentpen'); + toolbar = addToolbarButton(toolbar, 'premium_a', 'permanentpen'); + contextmenu = addContextmenuItem(contextmenu, 'configurepermanentpen'); + + // Format Painter. + plugins += ` formatpainter`; + toolbar = addToolbarButton(toolbar, 'premium_a', 'formatpainter'); + + // Link Checker. + plugins += ` linkchecker`; + contextmenu = addContextmenuItem(contextmenu, 'linkchecker'); + + // Table of Contents. + plugins += ` tableofcontents`; + toolbar = addToolbarButton(toolbar, 'premium_a', 'tableofcontents'); + + // Footnotes. + plugins += ` footnotes`; + toolbar = addToolbarButton(toolbar, 'premium_a', 'footnotes'); + menu = addMenubarItem(menu, 'insert', 'footnotes', 'tableofcontents'); + + // Powerpaste. + plugins += ` powerpaste`; + + return { + plugins, + toolbar, + menu, + contextmenu, + ...pluginsettings + }; +}; diff --git a/lib/editor/tiny/plugins/premium/amd/src/external.js b/lib/editor/tiny/plugins/premium/amd/src/external.js new file mode 100644 index 00000000000..da1946c3ce2 --- /dev/null +++ b/lib/editor/tiny/plugins/premium/amd/src/external.js @@ -0,0 +1,41 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Helper to get external content for Tiny Premium plugin. + * + * @module tiny_premium/external + * @copyright 2023 David Woloszyn + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import Ajax from 'core/ajax'; + +/** + * Due to the order items are initialise, options.js will not work in getting the API key. + * This external method is used to get the API key in time. + * + * @param {Number} contextId The context id + * @return {Promise} + */ +export const getApiKey = (contextId) => { + const request = { + methodname: 'tiny_premium_get_api_key', + args: { + contextid: contextId + } + }; + return Ajax.call([request])[0]; +}; diff --git a/lib/editor/tiny/plugins/premium/amd/src/plugin.js b/lib/editor/tiny/plugins/premium/amd/src/plugin.js new file mode 100644 index 00000000000..db9da575e85 --- /dev/null +++ b/lib/editor/tiny/plugins/premium/amd/src/plugin.js @@ -0,0 +1,87 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Tiny Premium plugin for Moodle. + * + * @module tiny_premium/plugin + * @copyright 2023 David Woloszyn + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import {getTinyMCE} from 'editor_tiny/loader'; +import {getPluginMetadata} from 'editor_tiny/utils'; +import {component, pluginName} from 'tiny_premium/common'; +import * as Configuration from 'tiny_premium/configuration'; +import {getApiKey} from 'tiny_premium/external'; +import Config from 'core/config'; + +const currentContextId = Config.contextid; + +// eslint-disable-next-line no-async-promise-executor +export default new Promise(async(resolve) => { + const [ + tinyMCE, + pluginMetadata, + externalData + ] = await Promise.all([ + getTinyMCE(), + getPluginMetadata(component, pluginName), + getApiKey(currentContextId) + ]); + + tinyMCE.PluginManager.add(`${component}/plugin`, () => { + return pluginMetadata; + }); + + // Load the Tiny Premium script using the provided API key. + await getTinyPremium(externalData.apikey); + + resolve([`${component}/plugin`, Configuration]); +}); + +let tinyPremiumPromise; + +/** + * Promise for Tiny Premium plugins script. + * + * @param {string} apikey + * @return {Promise} + */ +const getTinyPremium = (apikey) => { + if (tinyPremiumPromise) { + return tinyPremiumPromise; + } + + tinyPremiumPromise = new Promise((resolve, reject) => { + const head = document.querySelector('head'); + const script = document.createElement('script'); + script.dataset.tinymce = 'premium'; + script.src = `https://cdn.tiny.cloud/1/${apikey}/tinymce/6/plugins.min.js`; + script.referrerpolicy = "origin"; + + script.addEventListener('load', () => { + resolve(); + }, false); + + script.addEventListener('error', (err) => { + reject(err); + }, false); + + head.append(script); + }); + + return tinyPremiumPromise; +}; diff --git a/lib/editor/tiny/plugins/premium/classes/external/get_api_key.php b/lib/editor/tiny/plugins/premium/classes/external/get_api_key.php new file mode 100644 index 00000000000..fc3e9a65987 --- /dev/null +++ b/lib/editor/tiny/plugins/premium/classes/external/get_api_key.php @@ -0,0 +1,78 @@ +. + +namespace tiny_premium\external; + +use context; +use core_external\external_api; +use core_external\external_function_parameters; +use core_external\external_single_structure; +use core_external\external_value; + +/** + * External API for Tiny Premium. + * + * @package tiny_premium + * @copyright 2023 David Woloszyn + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class get_api_key extends external_api { + + /** + * Describes the parameters for Tiny Premium API key. + * + * @return external_function_parameters + * @since Moodle 4.3 + */ + public static function execute_parameters(): external_function_parameters { + return new external_function_parameters([ + 'contextid' => new external_value(PARAM_INT, 'The current context ID.', VALUE_REQUIRED), + ]); + } + + /** + * External function to get the Tiny Premium API key. + * + * @param int $contextid + * @return array + * @since Moodle 4.3 + */ + public static function execute(int $contextid): array { + [ + 'contextid' => $contextid, + ] = self::validate_parameters(self::execute_parameters(), [ + 'contextid' => $contextid, + ]); + + $context = context::instance_by_id($contextid); + self::validate_context($context); + return [ + 'apikey' => get_config('tiny_premium', 'apikey'), + ]; + } + + /** + * Describes the data returned from the external function. + * + * @return external_single_structure + * @since Moodle 4.3 + */ + public static function execute_returns(): external_single_structure { + return new external_single_structure([ + 'apikey' => new external_value(PARAM_ALPHANUM, 'The API key for Tiny Premium'), + ]); + } +} diff --git a/lib/editor/tiny/plugins/premium/classes/plugininfo.php b/lib/editor/tiny/plugins/premium/classes/plugininfo.php new file mode 100644 index 00000000000..09b11df295f --- /dev/null +++ b/lib/editor/tiny/plugins/premium/classes/plugininfo.php @@ -0,0 +1,49 @@ +. + +namespace tiny_premium; + +use context; +use editor_tiny\editor; +use editor_tiny\plugin; + +/** + * Tiny Premium plugin. + * + * @package tiny_premium + * @copyright 2023 David Woloszyn + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class plugininfo extends plugin { + + /** + * Determine if the plugin should be enabled by checking if the Tiny Premium API key is set. + * + * @param context $context The context that the editor is used within + * @param array $options The options passed in when requesting the editor + * @param array $fpoptions The filepicker options passed in when requesting the editor + * @param editor $editor The editor instance in which the plugin is initialised + * @return bool + */ + public static function is_enabled( + context $context, + array $options, + array $fpoptions, + ?editor $editor = null + ): bool { + return get_config('tiny_premium', 'apikey') != false; + } +} diff --git a/lib/editor/tiny/plugins/premium/classes/privacy/provider.php b/lib/editor/tiny/plugins/premium/classes/privacy/provider.php new file mode 100644 index 00000000000..984e7adc0c9 --- /dev/null +++ b/lib/editor/tiny/plugins/premium/classes/privacy/provider.php @@ -0,0 +1,37 @@ +. + +namespace tiny_premium\privacy; + +/** + * Privacy Subsystem implementation for the Premium plugin for TinyMCE. + * + * @package tiny_premium + * @copyright 2023 David Woloszyn + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class provider implements \core_privacy\local\metadata\null_provider { + + /** + * Get the language string identifier with the component's language + * file to explain why this plugin stores no data. + * + * @return string + */ + public static function get_reason(): string { + return 'privacy:metadata'; + } +} diff --git a/lib/editor/tiny/plugins/premium/db/services.php b/lib/editor/tiny/plugins/premium/db/services.php new file mode 100644 index 00000000000..b3e9e3ee62f --- /dev/null +++ b/lib/editor/tiny/plugins/premium/db/services.php @@ -0,0 +1,36 @@ +. + +/** + * Tiny Premium external functions and service definitions. + * + * @package tiny_premium + * @copyright 2023 David Woloszyn + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$functions = [ + 'tiny_premium_get_api_key' => [ + 'classname' => 'tiny_premium\external\get_api_key', + 'methodname' => 'execute', + 'description' => 'Get the Tiny Premium API key from Moodle', + 'type' => 'read', + 'capabilities' => '', + 'ajax' => true, + ], +]; diff --git a/lib/editor/tiny/plugins/premium/lang/en/tiny_premium.php b/lib/editor/tiny/plugins/premium/lang/en/tiny_premium.php new file mode 100644 index 00000000000..45291f449fe --- /dev/null +++ b/lib/editor/tiny/plugins/premium/lang/en/tiny_premium.php @@ -0,0 +1,31 @@ +. + +/** + * Strings for component 'tiny_premium', language 'en'. + * + * @package tiny_premium + * @category string + * @copyright 2023 David Woloszyn + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$string['pluginname'] = 'Tiny Premium'; +$string['apikey'] = 'API Key'; +$string['apikey_desc'] = 'Your Tiny Premium API Key requires a paid subscription. You can obtain your key by accessing your Tiny Cloud account page.'; +$string['privacy:metadata'] = 'The Tiny Premium plugin for TinyMCE does not store any personal data.'; diff --git a/lib/editor/tiny/plugins/premium/readme_moodle.txt b/lib/editor/tiny/plugins/premium/readme_moodle.txt new file mode 100644 index 00000000000..d0afd906ebb --- /dev/null +++ b/lib/editor/tiny/plugins/premium/readme_moodle.txt @@ -0,0 +1,12 @@ +Instructions for updating the Tiny Premium plugin for Moodle. + +A request to Tiny Cloud is made in the plugin.js file of this plugin. +This request passes the Tiny Premium API key as part of a URL. +The URL also contains the major version of Tiny and may need to be updated. + +The URL looks like this: https://cdn.tiny.cloud/1/YOUR_API_KEY/tinymce/6/plugins.min.js + +Notice that the version (6) is baked into the URL and may need revision. + +When upgrading, check Tiny Cloud's documentation regarding the correct API URL +to use. Go to https://www.tiny.cloud/docs/tinymce diff --git a/lib/editor/tiny/plugins/premium/settings.php b/lib/editor/tiny/plugins/premium/settings.php new file mode 100644 index 00000000000..737ed7ceeaf --- /dev/null +++ b/lib/editor/tiny/plugins/premium/settings.php @@ -0,0 +1,39 @@ +. + +/** + * Settings for the Tiny Premium plugin. + * + * @package tiny_premium + * @category admin + * @copyright 2023 David Woloszyn + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +if ($hassiteconfig) { + // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedIf + if ($ADMIN->fulltree) { + $setting = new admin_setting_configpasswordunmask( + 'tiny_premium/apikey', + get_string('apikey', 'tiny_premium'), + get_string('apikey_desc', 'tiny_premium'), + '', + ); + $settings->add($setting); + } +} diff --git a/lib/editor/tiny/plugins/premium/version.php b/lib/editor/tiny/plugins/premium/version.php new file mode 100644 index 00000000000..de44ec5e9ee --- /dev/null +++ b/lib/editor/tiny/plugins/premium/version.php @@ -0,0 +1,29 @@ +. + +/** + * Plugin version and other meta-data are defined here. + * + * @package tiny_premium + * @copyright 2023 David Woloszyn + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$plugin->version = 2023082200; +$plugin->requires = 2021051700; +$plugin->component = 'tiny_premium';