mirror of
https://github.com/moodle/moodle.git
synced 2025-03-20 07:30:01 +01:00
MDL-75078 editor_tiny: Improve configuration specification
Part of MDL-75966
This commit is contained in:
parent
05000e3e8b
commit
603c50e1be
11
lib/editor/tiny/amd/build/defaults.min.js
vendored
Normal file
11
lib/editor/tiny/amd/build/defaults.min.js
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
define("editor_tiny/defaults",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.getDefaultToolbar=_exports.getDefaultQuickbarsSelectionToolbar=_exports.getDefaultQuickbarsInsertToolbar=_exports.getDefaultQuickbarsImageToolbar=_exports.getDefaultMenu=_exports.getDefaultConfiguration=void 0;
|
||||
/**
|
||||
* TinyMCE Editor Upstream defaults.
|
||||
*
|
||||
* @module editor_tiny/editor
|
||||
* @copyright 2022 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
const getDefaultMenu=()=>({file:{title:"File",items:"newdocument restoredraft | preview | export print | deleteallconversations"},edit:{title:"Edit",items:"undo redo | cut copy paste pastetext | selectall | searchreplace"},view:{title:"View",items:"code | visualaid visualchars visualblocks | spellchecker | preview fullscreen | showcomments"},insert:{title:"Insert",items:"image link media addcomment pageembed template codesample inserttable | charmap emoticons hr | pagebreak nonbreaking anchor tableofcontents | insertdatetime"},format:{title:"Format",items:"bold italic underline strikethrough superscript subscript codeformat | styles blocks fontfamily fontsize align lineheight | forecolor backcolor | language | removeformat"},tools:{title:"Tools",items:"spellchecker spellcheckerlanguage | a11ycheck code wordcount"},table:{title:"Table",items:"inserttable | cell row column | advtablesort | tableprops deletetable"},help:{title:"Help",items:"help"}});_exports.getDefaultMenu=getDefaultMenu;const getDefaultToolbar=()=>[{name:"content",items:[]},{name:"styles",items:["styles"]},{name:"formatting",items:["bold","italic"]},{name:"history",items:["undo","redo"]},{name:"alignment",items:["alignleft","aligncenter","alignright","alignjustify"]},{name:"indentation",items:["outdent","indent"]},{name:"comments",items:["addcomment"]}];_exports.getDefaultToolbar=getDefaultToolbar;const getDefaultQuickbarsSelectionToolbar=()=>"bold italic | quicklink h2 h3 blockquote";_exports.getDefaultQuickbarsSelectionToolbar=getDefaultQuickbarsSelectionToolbar;const getDefaultQuickbarsInsertToolbar=()=>"quickimage quicktable";_exports.getDefaultQuickbarsInsertToolbar=getDefaultQuickbarsInsertToolbar;const getDefaultQuickbarsImageToolbar=()=>"alignleft aligncenter alignright";_exports.getDefaultQuickbarsImageToolbar=getDefaultQuickbarsImageToolbar;_exports.getDefaultConfiguration=()=>({toolbar_mode:"sliding",toolbar:[{name:"content",items:[]},{name:"styles",items:["styles"]},{name:"formatting",items:["bold","italic"]},{name:"history",items:["undo","redo"]},{name:"alignment",items:["alignleft","aligncenter","alignright","alignjustify"]},{name:"indentation",items:["outdent","indent"]},{name:"comments",items:["addcomment"]}],quickbars_selection_toolbar:"bold italic | quicklink h2 h3 blockquote",quickbars_insert_toolbar:"quickimage quicktable",quickbars_image_toolbar:"alignleft aligncenter alignright",menu:{file:{title:"File",items:"newdocument restoredraft | preview | export print | deleteallconversations"},edit:{title:"Edit",items:"undo redo | cut copy paste pastetext | selectall | searchreplace"},view:{title:"View",items:"code | visualaid visualchars visualblocks | spellchecker | preview fullscreen | showcomments"},insert:{title:"Insert",items:"image link media addcomment pageembed template codesample inserttable | charmap emoticons hr | pagebreak nonbreaking anchor tableofcontents | insertdatetime"},format:{title:"Format",items:"bold italic underline strikethrough superscript subscript codeformat | styles blocks fontfamily fontsize align lineheight | forecolor backcolor | language | removeformat"},tools:{title:"Tools",items:"spellchecker spellcheckerlanguage | a11ycheck code wordcount"},table:{title:"Table",items:"inserttable | cell row column | advtablesort | tableprops deletetable"},help:{title:"Help",items:"help"}},skin:"oxide"})}));
|
||||
|
||||
//# sourceMappingURL=defaults.min.js.map
|
1
lib/editor/tiny/amd/build/defaults.min.js.map
Normal file
1
lib/editor/tiny/amd/build/defaults.min.js.map
Normal file
File diff suppressed because one or more lines are too long
2
lib/editor/tiny/amd/build/editor.min.js
vendored
2
lib/editor/tiny/amd/build/editor.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3
lib/editor/tiny/amd/build/options.min.js
vendored
Normal file
3
lib/editor/tiny/amd/build/options.min.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
define("editor_tiny/options",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.register=_exports.getPluginOptionName=_exports.getMoodleLang=_exports.getInitialPluginConfiguration=_exports.getFilepickers=_exports.getFilePicker=_exports.getDraftItemId=_exports.getCurrentLanguage=_exports.getContextId=void 0;_exports.register=(editor,options)=>{const registerOption=editor.options.register,setOption=editor.options.set;registerOption("moodle:contextid",{processor:"number",default:0}),setOption("moodle:contextid",options.context),registerOption("moodle:filepickers",{processor:"object",default:{}}),setOption("moodle:filepickers",options.filepicker),registerOption("moodle:draftitemid",{processor:"number",default:0}),setOption("moodle:draftitemid",options.draftitemid),registerOption("moodle:currentLanguage",{processor:"string",default:"en"}),setOption("moodle:currentLanguage",options.currentLanguage),registerOption("moodle:language",{processor:"object",default:{}}),setOption("moodle:language",options.language)};_exports.getContextId=editor=>editor.options.get("moodle:contextid");_exports.getDraftItemId=editor=>editor.options.get("moodle:draftitemid");const getFilepickers=editor=>editor.options.get("moodle:filepickers");_exports.getFilepickers=getFilepickers;_exports.getFilePicker=(editor,type)=>getFilepickers(editor)[type];_exports.getMoodleLang=editor=>editor.options.get("moodle:language");_exports.getCurrentLanguage=editor=>editor.options.get("moodle:currentLanguage");_exports.getInitialPluginConfiguration=options=>{const config={};return Object.entries(options.plugins).forEach((_ref=>{var _pluginConfig$config;let[pluginName,pluginConfig]=_ref;Object.entries(null!==(_pluginConfig$config=pluginConfig.config)&&void 0!==_pluginConfig$config?_pluginConfig$config:{}).forEach((_ref2=>{let[optionName,value]=_ref2;config[getPluginOptionName(pluginName,optionName)]=value}))})),config};const getPluginOptionName=(pluginName,optionName)=>"".concat(pluginName,":").concat(optionName);_exports.getPluginOptionName=getPluginOptionName}));
|
||||
|
||||
//# sourceMappingURL=options.min.js.map
|
1
lib/editor/tiny/amd/build/options.min.js.map
Normal file
1
lib/editor/tiny/amd/build/options.min.js.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"options.min.js","sources":["../src/options.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Option helper for TinyMCE Editor Manager.\n *\n * @module editor_tiny/options\n * @copyright 2022 Andrew Lyons <andrew@nicols.co.uk>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst optionContextId = 'moodle:contextid';\nconst optionDraftItemId = 'moodle:draftitemid';\nconst filePickers = 'moodle:filepickers';\nconst optionsMoodleLang = 'moodle:language';\nconst currentLanguage = 'moodle:currentLanguage';\n\nexport const register = (editor, options) => {\n const registerOption = editor.options.register;\n const setOption = editor.options.set;\n\n registerOption(optionContextId, {\n processor: 'number',\n \"default\": 0,\n });\n setOption(optionContextId, options.context);\n\n registerOption(filePickers, {\n processor: 'object',\n \"default\": {},\n });\n setOption(filePickers, options.filepicker);\n\n registerOption(optionDraftItemId, {\n processor: 'number',\n \"default\": 0,\n });\n setOption(optionDraftItemId, options.draftitemid);\n\n registerOption(currentLanguage, {\n processor: 'string',\n \"default\": 'en',\n });\n setOption(currentLanguage, options.currentLanguage);\n\n // This is primarily used by the media plugin, but it may be re-used elsewhere so is included here as it is large.\n registerOption(optionsMoodleLang, {\n processor: 'object',\n \"default\": {},\n });\n setOption(optionsMoodleLang, options.language);\n};\n\nexport const getContextId = (editor) => editor.options.get(optionContextId);\nexport const getDraftItemId = (editor) => editor.options.get(optionDraftItemId);\nexport const getFilepickers = (editor) => editor.options.get(filePickers);\nexport const getFilePicker = (editor, type) => getFilepickers(editor)[type];\nexport const getMoodleLang = (editor) => editor.options.get(optionsMoodleLang);\nexport const getCurrentLanguage = (editor) => editor.options.get(currentLanguage);\n\n/**\n * Get a set of namespaced options for all defined plugins.\n *\n * @param {object} options\n * @returns {object}\n */\nexport const getInitialPluginConfiguration = (options) => {\n const config = {};\n\n Object.entries(options.plugins).forEach(([pluginName, pluginConfig]) => {\n const values = Object.entries(pluginConfig.config ?? {});\n values.forEach(([optionName, value]) => {\n config[getPluginOptionName(pluginName, optionName)] = value;\n });\n });\n\n return config;\n};\n\n/**\n * Get the namespaced option name for a plugin.\n *\n * @param {string} pluginName\n * @param {string} optionName\n * @returns {string}\n */\nexport const getPluginOptionName = (pluginName, optionName) => `${pluginName}:${optionName}`;\n"],"names":["editor","options","registerOption","register","setOption","set","processor","context","filepicker","draftitemid","currentLanguage","language","get","getFilepickers","type","config","Object","entries","plugins","forEach","_ref","pluginName","pluginConfig","_ref2","optionName","value","getPluginOptionName"],"mappings":"oXA6BwB,CAACA,OAAQC,iBACvBC,eAAiBF,OAAOC,QAAQE,SAChCC,UAAYJ,OAAOC,QAAQI,IAEjCH,eAVoB,mBAUY,CAC5BI,UAAW,iBACA,IAEfF,UAdoB,mBAcOH,QAAQM,SAEnCL,eAdgB,qBAcY,CACxBI,UAAW,iBACA,KAEfF,UAlBgB,qBAkBOH,QAAQO,YAE/BN,eArBsB,qBAqBY,CAC9BI,UAAW,iBACA,IAEfF,UAzBsB,qBAyBOH,QAAQQ,aAErCP,eAxBoB,yBAwBY,CAC5BI,UAAW,iBACA,OAEfF,UA5BoB,yBA4BOH,QAAQS,iBAGnCR,eAhCsB,kBAgCY,CAC9BI,UAAW,iBACA,KAEfF,UApCsB,kBAoCOH,QAAQU,iCAGZX,QAAWA,OAAOC,QAAQW,IA1C/B,4CA2COZ,QAAWA,OAAOC,QAAQW,IA1C/B,4BA2CbC,eAAkBb,QAAWA,OAAOC,QAAQW,IA1CrC,oFA2CS,CAACZ,OAAQc,OAASD,eAAeb,QAAQc,6BACxCd,QAAWA,OAAOC,QAAQW,IA3C9B,+CA4CSZ,QAAWA,OAAOC,QAAQW,IA3CrC,iEAmDsBX,gBACpCc,OAAS,UAEfC,OAAOC,QAAQhB,QAAQiB,SAASC,SAAQC,oCAAEC,WAAYC,mBACnCN,OAAOC,qCAAQK,aAAaP,4DAAU,IAC9CI,SAAQI,YAAEC,WAAYC,aACzBV,OAAOW,oBAAoBL,WAAYG,aAAeC,YAIvDV,cAUEW,oBAAsB,CAACL,WAAYG,uBAAkBH,uBAAcG"}
|
2
lib/editor/tiny/amd/build/utils.min.js
vendored
2
lib/editor/tiny/amd/build/utils.min.js
vendored
@ -1,3 +1,3 @@
|
||||
define("editor_tiny/utils",["exports","core/templates"],(function(_exports,_templates){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.getPluginConfiguration=_exports.getImagePath=_exports.getButtonImage=_exports.displayFilepicker=void 0;const getImagePath=function(identifier){let component=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"editor_tiny";return Promise.resolve(M.util.image_url(identifier,component))};_exports.getImagePath=getImagePath;_exports.getButtonImage=async function(identifier){let component=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"editor_tiny";return(0,_templates.renderForPromise)("editor_tiny/toolbar_button",{image:await getImagePath(identifier,component)})};_exports.getPluginConfiguration=(editor,plugin)=>{var _editor$moodleOptions;const config=null===(_editor$moodleOptions=editor.moodleOptions.plugins["tiny_".concat(plugin,"/plugin")])||void 0===_editor$moodleOptions?void 0:_editor$moodleOptions.config;return config||{}};_exports.displayFilepicker=(editor,filetype)=>new Promise(((resolve,reject)=>{if(editor.moodleOptions.filepicker[filetype]){const options={...editor.moodleOptions.filepicker[filetype],formcallback:resolve};M.core_filepicker.show(Y,options)}else reject("Unknown filetype ".concat(filetype))}))}));
|
||||
define("editor_tiny/utils",["exports","core/templates","./options"],(function(_exports,_templates,_options){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.getImagePath=_exports.getButtonImage=_exports.displayFilepicker=_exports.addToolbarButton=_exports.addMenubarItem=_exports.addContextmenuItem=void 0;const getImagePath=function(identifier){let component=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"editor_tiny";return Promise.resolve(M.util.image_url(identifier,component))};_exports.getImagePath=getImagePath;_exports.getButtonImage=async function(identifier){let component=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"editor_tiny";return(0,_templates.renderForPromise)("editor_tiny/toolbar_button",{image:await getImagePath(identifier,component)})};_exports.displayFilepicker=(editor,filetype)=>new Promise(((resolve,reject)=>{const configuration=(0,_options.getFilePicker)(editor,filetype);if(configuration){const options={...configuration,formcallback:resolve};M.core_filepicker.show(Y,options)}else reject("Unknown filetype ".concat(filetype))}));_exports.addToolbarButton=(toolbar,section,button)=>{if(!toolbar)return[{name:section,items:[button]}];return JSON.parse(JSON.stringify(toolbar)).map((item=>(item.name===section&&item.items.push(button),item)))};_exports.addMenubarItem=(menubar,section,menuitem)=>{if(!menubar){({})[section]={title:section,items:menuitem}}const mutatedMenubar=JSON.parse(JSON.stringify(menubar));return Array.from(Object.entries(mutatedMenubar)).forEach((_ref=>{let[name,menu]=_ref;name===section&&(menu.items="".concat(menu.items," ").concat(menuitem))})),mutatedMenubar};_exports.addContextmenuItem=function(contextmenu){const contextmenuItems=(null!=contextmenu?contextmenu:"").split(" ");for(var _len=arguments.length,menuitems=new Array(_len>1?_len-1:0),_key=1;_key<_len;_key++)menuitems[_key-1]=arguments[_key];return contextmenuItems.concat(menuitems).filter((item=>""!==item)).join(" ")}}));
|
||||
|
||||
//# sourceMappingURL=utils.min.js.map
|
File diff suppressed because one or more lines are too long
177
lib/editor/tiny/amd/src/defaults.js
Normal file
177
lib/editor/tiny/amd/src/defaults.js
Normal file
@ -0,0 +1,177 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
/* eslint-disable max-len, */
|
||||
|
||||
/**
|
||||
* TinyMCE Editor Upstream defaults.
|
||||
*
|
||||
* @module editor_tiny/editor
|
||||
* @copyright 2022 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* The upstream defaults for the TinyMCE Menu.
|
||||
*
|
||||
* This value is defined in the TinyMCE documentation, but not exported anywhere useful.
|
||||
* https://www.tiny.cloud/docs/tinymce/6/menus-configuration-options/#menu
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
export const getDefaultMenu = () => {
|
||||
return {
|
||||
file: {title: 'File', items: 'newdocument restoredraft | preview | export print | deleteallconversations'},
|
||||
edit: {title: 'Edit', items: 'undo redo | cut copy paste pastetext | selectall | searchreplace'},
|
||||
view: {title: 'View', items: 'code | visualaid visualchars visualblocks | spellchecker | preview fullscreen | showcomments'},
|
||||
insert: {title: 'Insert', items: 'image link media addcomment pageembed template codesample inserttable | charmap emoticons hr | pagebreak nonbreaking anchor tableofcontents | insertdatetime'},
|
||||
format: {title: 'Format', items: 'bold italic underline strikethrough superscript subscript codeformat | styles blocks fontfamily fontsize align lineheight | forecolor backcolor | language | removeformat'},
|
||||
tools: {title: 'Tools', items: 'spellchecker spellcheckerlanguage | a11ycheck code wordcount'},
|
||||
table: {title: 'Table', items: 'inserttable | cell row column | advtablesort | tableprops deletetable'},
|
||||
help: {title: 'Help', items: 'help'}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* The default toolbar configuration to use.
|
||||
*
|
||||
* This is based upon the default value used if no toolbar is specified.
|
||||
*
|
||||
* https://www.tiny.cloud/docs/tinymce/6/menus-configuration-options/#menu
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
export const getDefaultToolbar = () => {
|
||||
return [
|
||||
{
|
||||
name: 'content',
|
||||
items: [],
|
||||
},
|
||||
{
|
||||
name: 'styles',
|
||||
items: ['styles']
|
||||
},
|
||||
{
|
||||
name: 'formatting',
|
||||
items: [
|
||||
'bold',
|
||||
'italic'
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'history',
|
||||
items: [
|
||||
'undo',
|
||||
'redo'
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'alignment',
|
||||
items: [
|
||||
'alignleft',
|
||||
'aligncenter',
|
||||
'alignright',
|
||||
'alignjustify'
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'indentation',
|
||||
items: [
|
||||
'outdent',
|
||||
'indent'
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'comments',
|
||||
items: ['addcomment']
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* The default quickbars_insert_toolbar configuration to use.
|
||||
*
|
||||
* This is based upon the default value used if no toolbar is specified.
|
||||
*
|
||||
* https://www.tiny.cloud/docs/tinymce/6/quickbars/#quickbars_selection_toolbar
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
export const getDefaultQuickbarsSelectionToolbar = () => 'bold italic | quicklink h2 h3 blockquote';
|
||||
|
||||
/**
|
||||
* The default quickbars_insert_toolbar configuration to use.
|
||||
*
|
||||
* This is based upon the default value used if no toolbar is specified.
|
||||
*
|
||||
* https://www.tiny.cloud/docs/tinymce/6/quickbars/#quickbars_insert_toolbar
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
export const getDefaultQuickbarsInsertToolbar = () => 'quickimage quicktable';
|
||||
|
||||
/**
|
||||
* The default quickbars_insert_toolbar configuration to use.
|
||||
*
|
||||
* This is based upon the default value used if no toolbar is specified.
|
||||
*
|
||||
* https://www.tiny.cloud/docs/tinymce/6/quickbars/#quickbars_image_toolbar
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
export const getDefaultQuickbarsImageToolbar = () => 'alignleft aligncenter alignright';
|
||||
|
||||
/**
|
||||
* Get the default configuration provided by TinyMCE.
|
||||
*
|
||||
* @returns {object}
|
||||
*/
|
||||
export const getDefaultConfiguration = () => ({
|
||||
// Toolbar configuration.
|
||||
// https://www.tiny.cloud/docs/tinymce/6/toolbar-configuration-options/
|
||||
// TODO: Move this configuration to a passed-in option.
|
||||
// eslint-disable-next-line camelcase
|
||||
toolbar_mode: 'sliding',
|
||||
toolbar: getDefaultToolbar(),
|
||||
|
||||
// Quickbars Selection Toolbar configuration.
|
||||
// https://www.tiny.cloud/docs/tinymce/6/quickbars/#quickbars_selection_toolbar
|
||||
// eslint-disable-next-line camelcase
|
||||
quickbars_selection_toolbar: getDefaultQuickbarsSelectionToolbar(),
|
||||
|
||||
// Quickbars Select Toolbar configuration.
|
||||
// https://www.tiny.cloud/docs/tinymce/6/quickbars/#quickbars_insert_toolbar
|
||||
// eslint-disable-next-line camelcase
|
||||
quickbars_insert_toolbar: getDefaultQuickbarsInsertToolbar(),
|
||||
|
||||
// Quickbars Image Toolbar configuration.
|
||||
// https://www.tiny.cloud/docs/tinymce/6/quickbars/#quickbars_image_toolbar
|
||||
// eslint-disable-next-line camelcase
|
||||
quickbars_image_toolbar: getDefaultQuickbarsImageToolbar(),
|
||||
|
||||
|
||||
// Menu configuration.
|
||||
// https://www.tiny.cloud/docs/tinymce/6/menus-configuration-options/
|
||||
// TODO: Move this configuration to a passed-in option.
|
||||
menu: getDefaultMenu(),
|
||||
|
||||
// TODO Add mobile configuration.
|
||||
// Mobile configuration.
|
||||
// https://www.tiny.cloud/docs/tinymce/6/tinymce-for-mobile/
|
||||
// This will include mobile-specific toolbar, and menu options.
|
||||
|
||||
// Skins
|
||||
skin: 'oxide',
|
||||
});
|
@ -14,17 +14,17 @@
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Utility functions.
|
||||
* TinyMCE Editor Manager.
|
||||
*
|
||||
* @module editor_tiny/editor
|
||||
* @copyright 2022 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
import {
|
||||
getTinyMCE,
|
||||
baseUrl,
|
||||
} from './loader';
|
||||
|
||||
import Pending from 'core/pending';
|
||||
import {getDefaultConfiguration} from './defaults';
|
||||
import {getTinyMCE, baseUrl} from './loader';
|
||||
import * as Options from './options';
|
||||
|
||||
/**
|
||||
* Storage for the TinyMCE instances on the page.
|
||||
@ -45,6 +45,8 @@ let defaultOptions = {};
|
||||
* @return {Promise[]} A matching set of Promises relating to the requested plugins
|
||||
*/
|
||||
const importPluginList = async(pluginList) => {
|
||||
// Fetch all of the plugins from the list of plugins.
|
||||
// If a plugin contains a '/' then it is assumed to be a Moodle AMD module to import.
|
||||
const pluginHandlers = await Promise.all(pluginList.map(pluginPath => {
|
||||
if (pluginPath.indexOf('/') === -1) {
|
||||
// A standard TinyMCE Plugin.
|
||||
@ -54,6 +56,10 @@ const importPluginList = async(pluginList) => {
|
||||
return import(pluginPath);
|
||||
}));
|
||||
|
||||
// Normalise the plugin data to a list of plugin names.
|
||||
// Two formats are supported:
|
||||
// - a string; and
|
||||
// - an array whose first element is the plugin name, and the second element is the plugin configuration.
|
||||
const pluginNames = pluginHandlers.map((pluginConfig) => {
|
||||
if (typeof pluginConfig === 'string') {
|
||||
return pluginConfig;
|
||||
@ -64,6 +70,7 @@ const importPluginList = async(pluginList) => {
|
||||
return null;
|
||||
}).filter((value) => value);
|
||||
|
||||
// Fetch the list of pluginConfig handlers.
|
||||
const pluginConfig = pluginHandlers.map((pluginConfig) => {
|
||||
if (Array.isArray(pluginConfig)) {
|
||||
return pluginConfig[1];
|
||||
@ -77,10 +84,21 @@ const importPluginList = async(pluginList) => {
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetch the language data for the specified language.
|
||||
*
|
||||
* @param {string} language The language identifier
|
||||
* @returns {object}
|
||||
*/
|
||||
const fetchLanguage = (language) => fetch(
|
||||
`${M.cfg.wwwroot}/lib/editor/tiny/lang.php/${M.cfg.langrev}/${language}`
|
||||
).then(response => response.json());
|
||||
|
||||
/**
|
||||
* Get a list of all Editors in a Map, keyed by the DOM Node that the Editor is associated with.
|
||||
*
|
||||
* @returns {Map<Node, Editor>}
|
||||
*/
|
||||
export const getAllInstances = () => new Map(instanceMap.entries());
|
||||
|
||||
/**
|
||||
@ -119,6 +137,11 @@ export const setupForElementId = ({elementId, options}) => {
|
||||
return setupForTarget(target, options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialise the page with standard TinyMCE requirements.
|
||||
*
|
||||
* Currently this includes the language taken from the HTML lang property.
|
||||
*/
|
||||
const initialisePage = async() => {
|
||||
const lang = document.querySelector('html').lang;
|
||||
|
||||
@ -127,9 +150,18 @@ const initialisePage = async() => {
|
||||
};
|
||||
initialisePage();
|
||||
|
||||
const getPlugins = (options) => {
|
||||
if (options.plugins) {
|
||||
return options.plugins;
|
||||
/**
|
||||
* Get the list of plugins to load for the specified configuration.
|
||||
*
|
||||
* If the specified configuration does not include a plugin configuration, then return the default configuration.
|
||||
*
|
||||
* @param {object} options
|
||||
* @param {array} [options.plugins=null] The plugin list
|
||||
* @returns {object}
|
||||
*/
|
||||
const getPlugins = ({plugins = null} = {}) => {
|
||||
if (plugins) {
|
||||
return plugins;
|
||||
}
|
||||
|
||||
if (defaultOptions.plugins) {
|
||||
@ -139,9 +171,20 @@ const getPlugins = (options) => {
|
||||
return {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the standard configuration for the specified options.
|
||||
*
|
||||
* @param {Node} target
|
||||
* @param {tinyMCE} tinyMCE
|
||||
* @param {object} options
|
||||
* @param {Array} plugins
|
||||
* @returns {object}
|
||||
*/
|
||||
const getStandardConfig = (target, tinyMCE, options, plugins) => {
|
||||
const lang = document.querySelector('html').lang;
|
||||
return {
|
||||
|
||||
return Object.assign({}, getDefaultConfiguration(), {
|
||||
// eslint-disable-next-line camelcase
|
||||
base_url: baseUrl,
|
||||
|
||||
// Set the editor target.
|
||||
@ -150,10 +193,12 @@ const getStandardConfig = (target, tinyMCE, options, plugins) => {
|
||||
|
||||
// Set the language.
|
||||
// https://www.tiny.cloud/docs/tinymce/6/ui-localization/#language
|
||||
// eslint-disable-next-line camelcase
|
||||
language: lang,
|
||||
|
||||
// Load the editor stylesheet into the editor iframe.
|
||||
// https://www.tiny.cloud/docs/tinymce/6/add-css-options/
|
||||
// eslint-disable-next-line camelcase
|
||||
content_css: [
|
||||
options.css,
|
||||
],
|
||||
@ -169,58 +214,6 @@ const getStandardConfig = (target, tinyMCE, options, plugins) => {
|
||||
// eslint-disable-next-line camelcase
|
||||
a11y_advanced_options: true,
|
||||
|
||||
// Toolbar configuration.
|
||||
// https://www.tiny.cloud/docs/tinymce/6/toolbar-configuration-options/
|
||||
// TODO: Move this configuration to a passed-in option.
|
||||
// eslint-disable-next-line camelcase
|
||||
toolbar_mode: 'sliding',
|
||||
toolbar: [
|
||||
{
|
||||
name: 'history',
|
||||
items: [
|
||||
'undo',
|
||||
'redo'
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'styles',
|
||||
items: ['styles']
|
||||
},
|
||||
{
|
||||
name: 'formatting',
|
||||
items: [
|
||||
'bold',
|
||||
'italic'
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'alignment',
|
||||
items: [
|
||||
'alignleft',
|
||||
'aligncenter',
|
||||
'alignright',
|
||||
'alignjustify'
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'indentation',
|
||||
items: [
|
||||
'outdent',
|
||||
'indent'
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'comments',
|
||||
items: ['addcomment']
|
||||
},
|
||||
],
|
||||
|
||||
// Menu configuration.
|
||||
// https://www.tiny.cloud/docs/tinymce/6/menus-configuration-options/
|
||||
// TODO: Move this configuration to a passed-in option.
|
||||
menu: {
|
||||
},
|
||||
|
||||
// The list of plugins to include in the instance.
|
||||
// https://www.tiny.cloud/docs/tinymce/6/editor-important-options/#plugins
|
||||
plugins: [
|
||||
@ -238,14 +231,18 @@ const getStandardConfig = (target, tinyMCE, options, plugins) => {
|
||||
// Remove the "Upgrade" link for Tiny.
|
||||
// https://www.tiny.cloud/docs/tinymce/6/editor-premium-upgrade-promotion/
|
||||
promotion: false,
|
||||
};
|
||||
|
||||
setup: (editor) => {
|
||||
Options.register(editor, options);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Set up TinyMCE for the HTML Element.
|
||||
*
|
||||
* @param {HTMLElement} target
|
||||
* @param {Object} options The editor plugin configuration
|
||||
* @param {Object} [options={}] The editor plugin configuration
|
||||
* @return {Promise<TinyMCE>} The TinyMCE instance
|
||||
*/
|
||||
export const setupForTarget = async(target, options = {}) => {
|
||||
@ -254,21 +251,29 @@ export const setupForTarget = async(target, options = {}) => {
|
||||
return Promise.resolve(instance);
|
||||
}
|
||||
|
||||
// Register a new pending promise to ensure that Behat waits for the editor setup to complete before continuing.
|
||||
const pendingPromise = new Pending('editor_tiny/editor:setupForTarget');
|
||||
|
||||
// Get the list of plugins.
|
||||
const plugins = getPlugins(options);
|
||||
|
||||
// Fetch the tinyMCE API, and instantiate the plugins.
|
||||
const [tinyMCE, pluginValues] = await Promise.all([
|
||||
getTinyMCE(),
|
||||
importPluginList(Object.keys(plugins)),
|
||||
]);
|
||||
const {pluginNames, pluginConfig} = pluginValues;
|
||||
|
||||
// Allow plugins to modify the configuration.
|
||||
const instanceConfig = getStandardConfig(target, tinyMCE, options, pluginNames);
|
||||
pluginConfig.forEach((pluginConfig) => {
|
||||
if (typeof pluginConfig.configure === 'function') {
|
||||
Object.assign(instanceConfig, pluginConfig.configure(instanceConfig));
|
||||
Object.assign(instanceConfig, pluginConfig.configure(instanceConfig, options));
|
||||
}
|
||||
});
|
||||
Object.assign(instanceConfig, Options.getInitialPluginConfiguration(options));
|
||||
|
||||
// Initialise the editor instance for the given configuration.
|
||||
const [editor] = await tinyMCE.init(instanceConfig);
|
||||
|
||||
// Store the editor instance in the instanceMap and register its removal to remove it.
|
||||
@ -278,15 +283,17 @@ export const setupForTarget = async(target, options = {}) => {
|
||||
instanceMap.delete(target.targetElm);
|
||||
});
|
||||
|
||||
// Store the Moodle-specific options in the TinyMCE instance.
|
||||
// TODO: See if there is a more appropriate location for this config.
|
||||
// TinyMCE does support custom configuration options in its EditorOptions but these must be registered and spec'd.
|
||||
editor.moodleOptions = options;
|
||||
|
||||
pendingPromise.resolve();
|
||||
return editor;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the default editor configuration.
|
||||
*
|
||||
* This configuration is used when an editor is initialised without any configuration.
|
||||
*
|
||||
* @param {object} [options={}]
|
||||
*/
|
||||
export const configureDefaultEditor = (options = {}) => {
|
||||
defaultOptions = options;
|
||||
};
|
||||
|
99
lib/editor/tiny/amd/src/options.js
Normal file
99
lib/editor/tiny/amd/src/options.js
Normal file
@ -0,0 +1,99 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Option helper for TinyMCE Editor Manager.
|
||||
*
|
||||
* @module editor_tiny/options
|
||||
* @copyright 2022 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
const optionContextId = 'moodle:contextid';
|
||||
const optionDraftItemId = 'moodle:draftitemid';
|
||||
const filePickers = 'moodle:filepickers';
|
||||
const optionsMoodleLang = 'moodle:language';
|
||||
const currentLanguage = 'moodle:currentLanguage';
|
||||
|
||||
export const register = (editor, options) => {
|
||||
const registerOption = editor.options.register;
|
||||
const setOption = editor.options.set;
|
||||
|
||||
registerOption(optionContextId, {
|
||||
processor: 'number',
|
||||
"default": 0,
|
||||
});
|
||||
setOption(optionContextId, options.context);
|
||||
|
||||
registerOption(filePickers, {
|
||||
processor: 'object',
|
||||
"default": {},
|
||||
});
|
||||
setOption(filePickers, options.filepicker);
|
||||
|
||||
registerOption(optionDraftItemId, {
|
||||
processor: 'number',
|
||||
"default": 0,
|
||||
});
|
||||
setOption(optionDraftItemId, options.draftitemid);
|
||||
|
||||
registerOption(currentLanguage, {
|
||||
processor: 'string',
|
||||
"default": 'en',
|
||||
});
|
||||
setOption(currentLanguage, options.currentLanguage);
|
||||
|
||||
// This is primarily used by the media plugin, but it may be re-used elsewhere so is included here as it is large.
|
||||
registerOption(optionsMoodleLang, {
|
||||
processor: 'object',
|
||||
"default": {},
|
||||
});
|
||||
setOption(optionsMoodleLang, options.language);
|
||||
};
|
||||
|
||||
export const getContextId = (editor) => editor.options.get(optionContextId);
|
||||
export const getDraftItemId = (editor) => editor.options.get(optionDraftItemId);
|
||||
export const getFilepickers = (editor) => editor.options.get(filePickers);
|
||||
export const getFilePicker = (editor, type) => getFilepickers(editor)[type];
|
||||
export const getMoodleLang = (editor) => editor.options.get(optionsMoodleLang);
|
||||
export const getCurrentLanguage = (editor) => editor.options.get(currentLanguage);
|
||||
|
||||
/**
|
||||
* Get a set of namespaced options for all defined plugins.
|
||||
*
|
||||
* @param {object} options
|
||||
* @returns {object}
|
||||
*/
|
||||
export const getInitialPluginConfiguration = (options) => {
|
||||
const config = {};
|
||||
|
||||
Object.entries(options.plugins).forEach(([pluginName, pluginConfig]) => {
|
||||
const values = Object.entries(pluginConfig.config ?? {});
|
||||
values.forEach(([optionName, value]) => {
|
||||
config[getPluginOptionName(pluginName, optionName)] = value;
|
||||
});
|
||||
});
|
||||
|
||||
return config;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the namespaced option name for a plugin.
|
||||
*
|
||||
* @param {string} pluginName
|
||||
* @param {string} optionName
|
||||
* @returns {string}
|
||||
*/
|
||||
export const getPluginOptionName = (pluginName, optionName) => `${pluginName}:${optionName}`;
|
@ -14,6 +14,7 @@
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import {renderForPromise} from 'core/templates';
|
||||
import {getFilePicker} from './options';
|
||||
|
||||
/**
|
||||
* Get the image path for the specified image.
|
||||
@ -28,23 +29,6 @@ export const getButtonImage = async(identifier, component = 'editor_tiny') => re
|
||||
image: await getImagePath(identifier, component),
|
||||
});
|
||||
|
||||
/**
|
||||
* Get the plugin configuration for the specified plugin.
|
||||
*
|
||||
* @param {TinyMCE} editor
|
||||
* @param {string} plugin
|
||||
* @returns {object} The plugin configuration
|
||||
*/
|
||||
export const getPluginConfiguration = (editor, plugin) => {
|
||||
const config = editor.moodleOptions.plugins[`tiny_${plugin}/plugin`]?.config;
|
||||
|
||||
if (!config) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return config;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper to display a filepicker and return a Promise.
|
||||
*
|
||||
@ -55,9 +39,10 @@ export const getPluginConfiguration = (editor, plugin) => {
|
||||
* @returns {Promise<object>} The file object returned by the filepicker
|
||||
*/
|
||||
export const displayFilepicker = (editor, filetype) => new Promise((resolve, reject) => {
|
||||
if (editor.moodleOptions.filepicker[filetype]) {
|
||||
const configuration = getFilePicker(editor, filetype);
|
||||
if (configuration) {
|
||||
const options = {
|
||||
...editor.moodleOptions.filepicker[filetype],
|
||||
...configuration,
|
||||
formcallback: resolve,
|
||||
};
|
||||
M.core_filepicker.show(Y, options);
|
||||
@ -65,3 +50,72 @@ export const displayFilepicker = (editor, filetype) => new Promise((resolve, rej
|
||||
}
|
||||
reject(`Unknown filetype ${filetype}`);
|
||||
});
|
||||
|
||||
/**
|
||||
* Given a TinyMCE Toolbar configuration, add the specified button to the named section.
|
||||
*
|
||||
* @param {object} toolbar
|
||||
* @param {string} section
|
||||
* @param {string} button
|
||||
* @returns {object} The toolbar configuration
|
||||
*/
|
||||
export const addToolbarButton = (toolbar, section, button) => {
|
||||
if (!toolbar) {
|
||||
return [{
|
||||
name: section,
|
||||
items: [button],
|
||||
}];
|
||||
}
|
||||
|
||||
const mutatedToolbar = JSON.parse(JSON.stringify(toolbar));
|
||||
return mutatedToolbar.map((item) => {
|
||||
if (item.name === section) {
|
||||
item.items.push(button);
|
||||
}
|
||||
|
||||
return item;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a TinyMCE Menubar configuration, add the specified button to the named section.
|
||||
*
|
||||
* @param {object} menubar
|
||||
* @param {string} section
|
||||
* @param {string} menuitem
|
||||
* @returns {object}
|
||||
*/
|
||||
export const addMenubarItem = (menubar, section, menuitem) => {
|
||||
if (!menubar) {
|
||||
const emptyMenubar = {};
|
||||
emptyMenubar[section] = {
|
||||
title: section,
|
||||
items: menuitem,
|
||||
};
|
||||
}
|
||||
|
||||
const mutatedMenubar = JSON.parse(JSON.stringify(menubar));
|
||||
Array.from(Object.entries(mutatedMenubar)).forEach(([name, menu]) => {
|
||||
if (name === section) {
|
||||
menu.items = `${menu.items} ${menuitem}`;
|
||||
}
|
||||
});
|
||||
|
||||
return mutatedMenubar;
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a TinyMCE contextmenu configuration, add the specified button to the end.
|
||||
*
|
||||
* @param {string} contextmenu
|
||||
* @param {string[]} menuitems
|
||||
* @returns {string}
|
||||
*/
|
||||
export const addContextmenuItem = (contextmenu, ...menuitems) => {
|
||||
const contextmenuItems = (contextmenu ?? '').split(' ');
|
||||
|
||||
return contextmenuItems
|
||||
.concat(menuitems)
|
||||
.filter((item) => item !== '')
|
||||
.join(' ');
|
||||
};
|
||||
|
@ -171,10 +171,28 @@ class editor extends \texteditor {
|
||||
// File picker options.
|
||||
'filepicker' => $fpoptions,
|
||||
|
||||
'currentLanguage' => current_language(),
|
||||
|
||||
// Language options.
|
||||
'language' => [
|
||||
'currentlang' => current_language(),
|
||||
'installed' => get_string_manager()->get_list_of_translations(true),
|
||||
'available' => get_string_manager()->get_list_of_languages()
|
||||
],
|
||||
|
||||
// Plugin configuration.
|
||||
'plugins' => $this->manager->get_plugin_configuration($context, $options, $fpoptions),
|
||||
'plugins' => $this->manager->get_plugin_configuration($context, $options, $fpoptions, $this),
|
||||
];
|
||||
|
||||
foreach ($fpoptions as $fp) {
|
||||
// Guess the draftitemid for the editor.
|
||||
// Note: This is the best we can do at the moment.
|
||||
if (!empty($fp->itemid)) {
|
||||
$config->draftitemid = $fp->itemid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$configoptions = json_encode(convert_to_array($config));
|
||||
|
||||
// Note: This is not ideal but the editor does not have control over any HTML output.
|
||||
|
@ -27,46 +27,62 @@ use context;
|
||||
*/
|
||||
class manager {
|
||||
|
||||
/**
|
||||
* Get the configuration for all plugins.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
public function get_plugin_configuration(
|
||||
context $context,
|
||||
array $options = [],
|
||||
array $fpoptions = []
|
||||
array $fpoptions = [],
|
||||
?editor $editor = null
|
||||
): array {
|
||||
$disabledplugins = $this->get_disabled_plugins();
|
||||
|
||||
// Get the list of plugins.
|
||||
// Note: Disabled plugins are already removed from this list.
|
||||
$plugins = $this->get_shipped_plugins();
|
||||
|
||||
// Fetch configuration for Moodle plugins.
|
||||
$moodleplugins = \core_component::get_plugin_list_with_class('tiny', 'plugininfo');
|
||||
foreach ($moodleplugins as $plugin => $classname) {
|
||||
if (in_array($plugin, $disabledplugins)) {
|
||||
if (in_array($plugin, $disabledplugins) || in_array("{$plugin}/plugin", $disabledplugins)) {
|
||||
// Skip getting data for disabled plugins.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_a($classname, plugin::class, true)) {
|
||||
// Skip plugins that do not implement the plugin interface.
|
||||
debugging("Plugin {$plugin} does not implement the plugin interface", DEBUG_DEVELOPER);
|
||||
continue;
|
||||
}
|
||||
|
||||
$plugininfo = $classname::get_plugin_info();
|
||||
if (!$classname::is_enabled($context, $options, $fpoptions, $editor)) {
|
||||
// This plugin has disabled itself for some reason.
|
||||
// This is typical for media plugins where there is no file storage.
|
||||
continue;
|
||||
}
|
||||
|
||||
$config = $classname::get_plugin_configuration_for_context(
|
||||
// Get the plugin information, which includes the list of buttons, menu items, and configuration.
|
||||
$plugininfo = $classname::get_plugin_info(
|
||||
$context,
|
||||
$options,
|
||||
$fpoptions
|
||||
$fpoptions,
|
||||
$editor
|
||||
);
|
||||
|
||||
if (!empty($config)) {
|
||||
$plugininfo['config'] = $config;
|
||||
}
|
||||
|
||||
// We suffix the plugin name for Moodle plugins with /plugin to avoid conflicts with Tiny plugins.
|
||||
$plugins["{$plugin}/plugin"] = $plugininfo;
|
||||
}
|
||||
|
||||
$plugins = array_filter($plugins, function ($plugin) use ($disabledplugins) {
|
||||
return !in_array($plugin, $disabledplugins);
|
||||
}, ARRAY_FILTER_USE_KEY);
|
||||
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,39 @@ use context;
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
abstract class plugin {
|
||||
public static function get_plugin_info(): array {
|
||||
/**
|
||||
* Whether the plugin is enabled
|
||||
*
|
||||
* @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 boolean
|
||||
*/
|
||||
public static function is_enabled(
|
||||
context $context,
|
||||
array $options,
|
||||
array $fpoptions,
|
||||
?editor $editor = null
|
||||
): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plugin information for the plugin.
|
||||
*
|
||||
* @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 array
|
||||
*/
|
||||
final public static function get_plugin_info(
|
||||
context $context,
|
||||
array $options,
|
||||
array $fpoptions,
|
||||
?editor $editor = null
|
||||
): array {
|
||||
$plugindata = [];
|
||||
|
||||
if (is_a(static::class, plugin_with_buttons::class, true)) {
|
||||
@ -44,18 +76,10 @@ abstract class plugin {
|
||||
$plugindata['menuitems'] = static::get_available_menuitems();
|
||||
}
|
||||
|
||||
return $plugindata;
|
||||
}
|
||||
|
||||
public static function get_plugin_configuration_for_context(
|
||||
context $context,
|
||||
array $options,
|
||||
array $fpoptions
|
||||
): array {
|
||||
if (is_a(static::class, plugin_with_configuration::class, true)) {
|
||||
return static::get_plugin_configuration_for_context($context, $options, $fpoptions);
|
||||
$plugindata['config'] = static::get_plugin_configuration_for_context($context, $options, $fpoptions, $editor);
|
||||
}
|
||||
|
||||
return [];
|
||||
return $plugindata;
|
||||
}
|
||||
}
|
||||
|
@ -32,11 +32,13 @@ interface plugin_with_configuration {
|
||||
* @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 array
|
||||
*/
|
||||
public static function get_plugin_configuration_for_context(
|
||||
context $context,
|
||||
array $options,
|
||||
array $fpoptions
|
||||
array $fpoptions,
|
||||
?editor $editor = null
|
||||
): array;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user