diff --git a/public/lib/editor/tiny/plugins/media/amd/build/usedfiles.min.js b/public/lib/editor/tiny/plugins/media/amd/build/usedfiles.min.js index c20a7f5e956..e1e953e1abd 100644 --- a/public/lib/editor/tiny/plugins/media/amd/build/usedfiles.min.js +++ b/public/lib/editor/tiny/plugins/media/amd/build/usedfiles.min.js @@ -5,6 +5,6 @@ define("tiny_media/usedfiles",["exports","core/templates","core/config"],(functi * @module tiny_media/usedfiles * @copyright 2022, Stevani Andolo * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */(Templates),_config=(obj=_config)&&obj.__esModule?obj:{default:obj};class UsedFileManager{constructor(userContext,itemId,elementId){this.files=this.getFiles(),this.userContext=userContext,this.itemId=itemId,this.elementId=elementId}getElementId(){return this.elementId}getUsedFiles(){const editor=window.parent.tinymce.EditorManager.get(this.getElementId());if(!editor)return window.console.error("Editor not found for ".concat(this.getElementId())),[];const content=editor.getContent(),baseUrl="".concat(_config.default.wwwroot,"/draftfile.php/").concat(this.userContext,"/user/draft/").concat(this.itemId,"/"),pattern=new RegExp("[\"']"+baseUrl.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&")+"(?.+?)[\\?\"']","gm");return[...content.matchAll(pattern)].map((match=>decodeURIComponent(match.groups.filename)))}findUnusedFiles(usedFiles){return Object.entries(this.files).filter((_ref=>{let[filename]=_ref;return!usedFiles.includes(filename)})).map((_ref2=>{let[filename]=_ref2;return filename}))}findMissingFiles(usedFiles){return usedFiles.filter((filename=>!this.files.hasOwnProperty(filename)))}updateFiles(){const form=document.querySelector("form"),usedFiles=this.getUsedFiles(),unusedFiles=this.findUnusedFiles(usedFiles),missingFiles=this.findMissingFiles(usedFiles);return form.querySelectorAll('input[type=checkbox][name^="deletefile"]').forEach((checkbox=>{unusedFiles.includes(checkbox.dataset.filename)||checkbox.closest(".fitem").remove()})),form.classList.toggle("has-missing-files",!!missingFiles.length),form.classList.toggle("has-unused-files",!!unusedFiles.length),Templates.renderForPromise("tiny_media/missingfiles",{missingFiles:missingFiles}).then((_ref3=>{let{html:html,js:js}=_ref3;Templates.replaceNodeContents(form.querySelector(".missing-files"),html,js)}))}getFiles(){const files={};return document.querySelectorAll('input[type=checkbox][name^="deletefile"]').forEach((input=>{files[input.dataset.filename]=input.dataset.filehash})),files}}_exports.init=(files,usercontext,itemid,elementid)=>{const manager=new UsedFileManager(files,usercontext,itemid,elementid);return manager.updateFiles(),manager}})); + */(Templates),_config=(obj=_config)&&obj.__esModule?obj:{default:obj};class UsedFileManager{constructor(userContext,itemId,elementId){this.files=this.getFiles(),this.userContext=userContext,this.itemId=itemId,this.elementId=elementId}getElementId(){return this.elementId}getUsedFiles(){const editor=window.parent.tinymce.EditorManager.get(this.getElementId());if(!editor)return window.console.error("Editor not found for ".concat(this.getElementId())),[];const content=editor.getContent(),baseUrl="".concat(_config.default.wwwroot,"/draftfile.php/").concat(this.userContext,"/user/draft/").concat(this.itemId,"/"),pattern=new RegExp("[\"'\\s>]"+baseUrl.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&")+"(?.+?)[\\?\"'\\s<]","gm");return[...content.matchAll(pattern)].map((match=>decodeURIComponent(match.groups.filename)))}findUnusedFiles(usedFiles){return Object.entries(this.files).filter((_ref=>{let[filename]=_ref;return!usedFiles.includes(filename)})).map((_ref2=>{let[filename]=_ref2;return filename}))}findMissingFiles(usedFiles){return usedFiles.filter((filename=>!this.files.hasOwnProperty(filename)))}updateFiles(){const form=document.querySelector("form"),usedFiles=this.getUsedFiles(),unusedFiles=this.findUnusedFiles(usedFiles),missingFiles=this.findMissingFiles(usedFiles);return form.querySelectorAll('input[type=checkbox][name^="deletefile"]').forEach((checkbox=>{unusedFiles.includes(checkbox.dataset.filename)||checkbox.closest(".fitem").remove()})),form.classList.toggle("has-missing-files",!!missingFiles.length),form.classList.toggle("has-unused-files",!!unusedFiles.length),Templates.renderForPromise("tiny_media/missingfiles",{missingFiles:missingFiles}).then((_ref3=>{let{html:html,js:js}=_ref3;Templates.replaceNodeContents(form.querySelector(".missing-files"),html,js)}))}getFiles(){const files={};return document.querySelectorAll('input[type=checkbox][name^="deletefile"]').forEach((input=>{files[input.dataset.filename]=input.dataset.filehash})),files}}_exports.init=(files,usercontext,itemid,elementid)=>{const manager=new UsedFileManager(files,usercontext,itemid,elementid);return manager.updateFiles(),manager}})); //# sourceMappingURL=usedfiles.min.js.map \ No newline at end of file diff --git a/public/lib/editor/tiny/plugins/media/amd/build/usedfiles.min.js.map b/public/lib/editor/tiny/plugins/media/amd/build/usedfiles.min.js.map index cd3c083c514..10e1d654d53 100644 --- a/public/lib/editor/tiny/plugins/media/amd/build/usedfiles.min.js.map +++ b/public/lib/editor/tiny/plugins/media/amd/build/usedfiles.min.js.map @@ -1 +1 @@ -{"version":3,"file":"usedfiles.min.js","sources":["../src/usedfiles.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 Media Manager usedfiles.\n *\n * @module tiny_media/usedfiles\n * @copyright 2022, Stevani Andolo \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport * as Templates from 'core/templates';\nimport Config from 'core/config';\n\nclass UsedFileManager {\n constructor(userContext, itemId, elementId) {\n this.files = this.getFiles();\n this.userContext = userContext;\n this.itemId = itemId;\n this.elementId = elementId;\n }\n\n getElementId() {\n return this.elementId;\n }\n\n getUsedFiles() {\n const editor = window.parent.tinymce.EditorManager.get(this.getElementId());\n if (!editor) {\n window.console.error(`Editor not found for ${this.getElementId()}`);\n return [];\n }\n const content = editor.getContent();\n const baseUrl = `${Config.wwwroot}/draftfile.php/${this.userContext}/user/draft/${this.itemId}/`;\n const pattern = new RegExp(\"[\\\"']\" + baseUrl.replace(/[-/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&') + \"(?.+?)[\\\\?\\\"']\", 'gm');\n\n const usedFiles = [...content.matchAll(pattern)].map((match) => decodeURIComponent(match.groups.filename));\n\n return usedFiles;\n }\n\n // Return an array of unused files.\n findUnusedFiles(usedFiles) {\n return Object.entries(this.files)\n .filter(([filename]) => !usedFiles.includes(filename))\n .map(([filename]) => filename);\n }\n\n // Return an array of missing files.\n findMissingFiles(usedFiles) {\n return usedFiles.filter((filename) => !this.files.hasOwnProperty(filename));\n }\n\n updateFiles() {\n const form = document.querySelector('form');\n const usedFiles = this.getUsedFiles();\n const unusedFiles = this.findUnusedFiles(usedFiles);\n const missingFiles = this.findMissingFiles(usedFiles);\n\n form.querySelectorAll('input[type=checkbox][name^=\"deletefile\"]').forEach((checkbox) => {\n if (!unusedFiles.includes(checkbox.dataset.filename)) {\n checkbox.closest('.fitem').remove();\n }\n });\n\n form.classList.toggle('has-missing-files', !!missingFiles.length);\n form.classList.toggle('has-unused-files', !!unusedFiles.length);\n\n return Templates.renderForPromise('tiny_media/missingfiles', {\n missingFiles,\n }).then(({html, js}) => {\n Templates.replaceNodeContents(form.querySelector('.missing-files'), html, js);\n return;\n });\n }\n\n /**\n * Retrieves a list of existing files selected for deletion.\n *\n * @returns {Object} An object where the keys are filenames and the values are file hashes.\n *\n */\n getFiles() {\n const files = {};\n document.querySelectorAll('input[type=checkbox][name^=\"deletefile\"]').forEach(input => {\n files[input.dataset.filename] = input.dataset.filehash;\n });\n return files;\n }\n}\n\nexport const init = (files, usercontext, itemid, elementid) => {\n const manager = new UsedFileManager(files, usercontext, itemid, elementid);\n manager.updateFiles();\n\n return manager;\n};\n"],"names":["UsedFileManager","constructor","userContext","itemId","elementId","files","this","getFiles","getElementId","getUsedFiles","editor","window","parent","tinymce","EditorManager","get","console","error","content","getContent","baseUrl","Config","wwwroot","pattern","RegExp","replace","matchAll","map","match","decodeURIComponent","groups","filename","findUnusedFiles","usedFiles","Object","entries","filter","_ref","includes","_ref2","findMissingFiles","hasOwnProperty","updateFiles","form","document","querySelector","unusedFiles","missingFiles","querySelectorAll","forEach","checkbox","dataset","closest","remove","classList","toggle","length","Templates","renderForPromise","then","_ref3","html","js","replaceNodeContents","input","filehash","usercontext","itemid","elementid","manager"],"mappings":";;;;;;;+EA0BMA,gBACFC,YAAYC,YAAaC,OAAQC,gBACxBC,MAAQC,KAAKC,gBACbL,YAAcA,iBACdC,OAASA,YACTC,UAAYA,UAGrBI,sBACWF,KAAKF,UAGhBK,qBACUC,OAASC,OAAOC,OAAOC,QAAQC,cAAcC,IAAIT,KAAKE,oBACvDE,cACDC,OAAOK,QAAQC,qCAA8BX,KAAKE,iBAC3C,SAELU,QAAUR,OAAOS,aACjBC,kBAAaC,gBAAOC,kCAAyBhB,KAAKJ,mCAA0BI,KAAKH,YACjFoB,QAAU,IAAIC,OAAO,QAAUJ,QAAQK,QAAQ,wBAAyB,QAAU,2BAA4B,YAElG,IAAIP,QAAQQ,SAASH,UAAUI,KAAKC,OAAUC,mBAAmBD,MAAME,OAAOC,YAMpGC,gBAAgBC,kBACLC,OAAOC,QAAQ7B,KAAKD,OACtB+B,QAAOC,WAAEN,sBAAeE,UAAUK,SAASP,aAC3CJ,KAAIY,YAAER,uBAAcA,YAI7BS,iBAAiBP,kBACNA,UAAUG,QAAQL,WAAczB,KAAKD,MAAMoC,eAAeV,YAGrEW,oBACUC,KAAOC,SAASC,cAAc,QAC9BZ,UAAY3B,KAAKG,eACjBqC,YAAcxC,KAAK0B,gBAAgBC,WACnCc,aAAezC,KAAKkC,iBAAiBP,kBAE3CU,KAAKK,iBAAiB,4CAA4CC,SAASC,WAClEJ,YAAYR,SAASY,SAASC,QAAQpB,WACvCmB,SAASE,QAAQ,UAAUC,YAInCV,KAAKW,UAAUC,OAAO,sBAAuBR,aAAaS,QAC1Db,KAAKW,UAAUC,OAAO,qBAAsBT,YAAYU,QAEjDC,UAAUC,iBAAiB,0BAA2B,CACzDX,aAAAA,eACDY,MAAKC,YAACC,KAACA,KAADC,GAAOA,UACZL,UAAUM,oBAAoBpB,KAAKE,cAAc,kBAAmBgB,KAAMC,OAWjFvD,iBACSF,MAAQ,UACduC,SAASI,iBAAiB,4CAA4CC,SAAQe,QAC1E3D,MAAM2D,MAAMb,QAAQpB,UAAYiC,MAAMb,QAAQc,YAE3C5D,qBAIK,CAACA,MAAO6D,YAAaC,OAAQC,mBACvCC,QAAU,IAAIrE,gBAAgBK,MAAO6D,YAAaC,OAAQC,kBAChEC,QAAQ3B,cAED2B"} \ No newline at end of file +{"version":3,"file":"usedfiles.min.js","sources":["../src/usedfiles.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 Media Manager usedfiles.\n *\n * @module tiny_media/usedfiles\n * @copyright 2022, Stevani Andolo \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport * as Templates from 'core/templates';\nimport Config from 'core/config';\n\nclass UsedFileManager {\n constructor(userContext, itemId, elementId) {\n this.files = this.getFiles();\n this.userContext = userContext;\n this.itemId = itemId;\n this.elementId = elementId;\n }\n\n getElementId() {\n return this.elementId;\n }\n\n getUsedFiles() {\n const editor = window.parent.tinymce.EditorManager.get(this.getElementId());\n if (!editor) {\n window.console.error(`Editor not found for ${this.getElementId()}`);\n return [];\n }\n const content = editor.getContent();\n const baseUrl = `${Config.wwwroot}/draftfile.php/${this.userContext}/user/draft/${this.itemId}/`;\n\n // Match any draft file contained within quotes, whitespace, or between html elements.\n const pattern = new RegExp(\n \"[\\\"'\\\\s>]\" + baseUrl.replace(/[-/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&') + \"(?.+?)[\\\\?\\\"'\\\\s<]\",\n 'gm'\n );\n\n return [...content.matchAll(pattern)].map((match) => decodeURIComponent(match.groups.filename));\n }\n\n // Return an array of unused files.\n findUnusedFiles(usedFiles) {\n return Object.entries(this.files)\n .filter(([filename]) => !usedFiles.includes(filename))\n .map(([filename]) => filename);\n }\n\n // Return an array of missing files.\n findMissingFiles(usedFiles) {\n return usedFiles.filter((filename) => !this.files.hasOwnProperty(filename));\n }\n\n updateFiles() {\n const form = document.querySelector('form');\n const usedFiles = this.getUsedFiles();\n const unusedFiles = this.findUnusedFiles(usedFiles);\n const missingFiles = this.findMissingFiles(usedFiles);\n\n form.querySelectorAll('input[type=checkbox][name^=\"deletefile\"]').forEach((checkbox) => {\n if (!unusedFiles.includes(checkbox.dataset.filename)) {\n checkbox.closest('.fitem').remove();\n }\n });\n\n form.classList.toggle('has-missing-files', !!missingFiles.length);\n form.classList.toggle('has-unused-files', !!unusedFiles.length);\n\n return Templates.renderForPromise('tiny_media/missingfiles', {\n missingFiles,\n }).then(({html, js}) => {\n Templates.replaceNodeContents(form.querySelector('.missing-files'), html, js);\n return;\n });\n }\n\n /**\n * Retrieves a list of existing files selected for deletion.\n *\n * @returns {Object} An object where the keys are filenames and the values are file hashes.\n *\n */\n getFiles() {\n const files = {};\n document.querySelectorAll('input[type=checkbox][name^=\"deletefile\"]').forEach(input => {\n files[input.dataset.filename] = input.dataset.filehash;\n });\n return files;\n }\n}\n\nexport const init = (files, usercontext, itemid, elementid) => {\n const manager = new UsedFileManager(files, usercontext, itemid, elementid);\n manager.updateFiles();\n\n return manager;\n};\n"],"names":["UsedFileManager","constructor","userContext","itemId","elementId","files","this","getFiles","getElementId","getUsedFiles","editor","window","parent","tinymce","EditorManager","get","console","error","content","getContent","baseUrl","Config","wwwroot","pattern","RegExp","replace","matchAll","map","match","decodeURIComponent","groups","filename","findUnusedFiles","usedFiles","Object","entries","filter","_ref","includes","_ref2","findMissingFiles","hasOwnProperty","updateFiles","form","document","querySelector","unusedFiles","missingFiles","querySelectorAll","forEach","checkbox","dataset","closest","remove","classList","toggle","length","Templates","renderForPromise","then","_ref3","html","js","replaceNodeContents","input","filehash","usercontext","itemid","elementid","manager"],"mappings":";;;;;;;+EA0BMA,gBACFC,YAAYC,YAAaC,OAAQC,gBACxBC,MAAQC,KAAKC,gBACbL,YAAcA,iBACdC,OAASA,YACTC,UAAYA,UAGrBI,sBACWF,KAAKF,UAGhBK,qBACUC,OAASC,OAAOC,OAAOC,QAAQC,cAAcC,IAAIT,KAAKE,oBACvDE,cACDC,OAAOK,QAAQC,qCAA8BX,KAAKE,iBAC3C,SAELU,QAAUR,OAAOS,aACjBC,kBAAaC,gBAAOC,kCAAyBhB,KAAKJ,mCAA0BI,KAAKH,YAGjFoB,QAAU,IAAIC,OAChB,YAAcJ,QAAQK,QAAQ,wBAAyB,QAAU,+BACjE,YAGG,IAAIP,QAAQQ,SAASH,UAAUI,KAAKC,OAAUC,mBAAmBD,MAAME,OAAOC,YAIzFC,gBAAgBC,kBACLC,OAAOC,QAAQ7B,KAAKD,OACtB+B,QAAOC,WAAEN,sBAAeE,UAAUK,SAASP,aAC3CJ,KAAIY,YAAER,uBAAcA,YAI7BS,iBAAiBP,kBACNA,UAAUG,QAAQL,WAAczB,KAAKD,MAAMoC,eAAeV,YAGrEW,oBACUC,KAAOC,SAASC,cAAc,QAC9BZ,UAAY3B,KAAKG,eACjBqC,YAAcxC,KAAK0B,gBAAgBC,WACnCc,aAAezC,KAAKkC,iBAAiBP,kBAE3CU,KAAKK,iBAAiB,4CAA4CC,SAASC,WAClEJ,YAAYR,SAASY,SAASC,QAAQpB,WACvCmB,SAASE,QAAQ,UAAUC,YAInCV,KAAKW,UAAUC,OAAO,sBAAuBR,aAAaS,QAC1Db,KAAKW,UAAUC,OAAO,qBAAsBT,YAAYU,QAEjDC,UAAUC,iBAAiB,0BAA2B,CACzDX,aAAAA,eACDY,MAAKC,YAACC,KAACA,KAADC,GAAOA,UACZL,UAAUM,oBAAoBpB,KAAKE,cAAc,kBAAmBgB,KAAMC,OAWjFvD,iBACSF,MAAQ,UACduC,SAASI,iBAAiB,4CAA4CC,SAAQe,QAC1E3D,MAAM2D,MAAMb,QAAQpB,UAAYiC,MAAMb,QAAQc,YAE3C5D,qBAIK,CAACA,MAAO6D,YAAaC,OAAQC,mBACvCC,QAAU,IAAIrE,gBAAgBK,MAAO6D,YAAaC,OAAQC,kBAChEC,QAAQ3B,cAED2B"} \ No newline at end of file diff --git a/public/lib/editor/tiny/plugins/media/amd/src/usedfiles.js b/public/lib/editor/tiny/plugins/media/amd/src/usedfiles.js index 0d23f6a72cc..050fcca22f3 100644 --- a/public/lib/editor/tiny/plugins/media/amd/src/usedfiles.js +++ b/public/lib/editor/tiny/plugins/media/amd/src/usedfiles.js @@ -44,11 +44,14 @@ class UsedFileManager { } const content = editor.getContent(); const baseUrl = `${Config.wwwroot}/draftfile.php/${this.userContext}/user/draft/${this.itemId}/`; - const pattern = new RegExp("[\"']" + baseUrl.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&') + "(?.+?)[\\?\"']", 'gm'); - const usedFiles = [...content.matchAll(pattern)].map((match) => decodeURIComponent(match.groups.filename)); + // Match any draft file contained within quotes, whitespace, or between html elements. + const pattern = new RegExp( + "[\"'\\s>]" + baseUrl.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&') + "(?.+?)[\\?\"'\\s<]", + 'gm' + ); - return usedFiles; + return [...content.matchAll(pattern)].map((match) => decodeURIComponent(match.groups.filename)); } // Return an array of unused files.