diff --git a/public/lib/editor/tiny/amd/build/content.min.js b/public/lib/editor/tiny/amd/build/content.min.js
index f820606f3c7..ab7c4dbc2c9 100644
--- a/public/lib/editor/tiny/amd/build/content.min.js
+++ b/public/lib/editor/tiny/amd/build/content.min.js
@@ -1,3 +1,3 @@
-define("editor_tiny/content",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.addSVGSupport=_exports.addMathMLSupport=void 0;_exports.addMathMLSupport=editor=>{editor.on("PreInit",(()=>{editor.schema.addCustomElements({math:{extends:"div"},"tiny-math-span":{extends:"span"},"tiny-math-block":{extends:"div"}}),editor.parser.addNodeFilter("math",(nodes=>nodes.forEach((node=>{if(node.parent&&("tiny-math-block"===node.parent.name||"tiny-math-span"===node.parent.name))return;const displayMode=(node=>{const style=node.attr("style");return null!=style&&style.includes("display")&&style.match(/display:[^;]*inline/)?"tiny-math-span":"tiny-math-block"})(node);node.wrap(editor.editorManager.html.Node.create(displayMode,{contenteditable:"false"}))})))),editor.serializer.addNodeFilter("tiny-math-span, tiny-math-block",((nodes,name)=>nodes.forEach((node=>{const displayMode=name.replace("tiny-math-","");node.children().forEach((child=>{const currentStyle=child.attr("style");currentStyle?child.attr("style","".concat(currentStyle,";display: ").concat(displayMode)):child.attr("style","display: ".concat(displayMode))})),node.unwrap()}))))}))};_exports.addSVGSupport=editor=>{editor.on("PreInit",(()=>{editor.schema.addCustomElements({svg:{extends:"div"},"tiny-svg-block":{extends:"div"}}),editor.parser.addNodeFilter("svg",(nodes=>nodes.forEach((node=>{node.wrap(editor.editorManager.html.Node.create("tiny-svg-block",{contenteditable:"false"}))})))),editor.serializer.addNodeFilter("tiny-svg-block",(nodes=>nodes.forEach((node=>{node.unwrap()}))))}))}}));
+define("editor_tiny/content",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.addSVGSupport=_exports.addMathMLSupport=void 0;_exports.addMathMLSupport=editor=>{editor.on("PreInit",(()=>{editor.schema.addCustomElements({math:{extends:"div"},"tiny-math-span":{extends:"span"},"tiny-math-block":{extends:"div"}}),editor.parser.addNodeFilter("math",(nodes=>nodes.forEach((node=>{if(node.parent&&("tiny-math-block"===node.parent.name||"tiny-math-span"===node.parent.name))return;const displayMode=(node=>{const style=node.attr("style");return null!=style&&style.includes("display")&&style.match(/display:[^;]*inline/)?"tiny-math-span":"tiny-math-block"})(node);node.wrap(editor.editorManager.html.Node.create(displayMode,{contenteditable:"false"}))})))),editor.serializer.addNodeFilter("tiny-math-span, tiny-math-block",((nodes,name)=>nodes.forEach((node=>{const displayMode=name.replace("tiny-math-","");node.children().forEach((child=>{const currentStyle=child.attr("style");currentStyle?child.attr("style","".concat(currentStyle,";display: ").concat(displayMode)):child.attr("style","display: ".concat(displayMode))})),node.unwrap()}))))}))};_exports.addSVGSupport=editor=>{editor.on("PreInit",(()=>{editor.schema.addCustomElements({svg:{extends:"div",attributes:["id","tabindex","lang","xml:space","class","style","x","y","width","height","viewBox","preserveAspectRatio","transform"]},"tiny-svg-block":{extends:"div"}}),editor.parser.addNodeFilter("svg",(nodes=>nodes.forEach((node=>{node.wrap(editor.editorManager.html.Node.create("tiny-svg-block",{contenteditable:"false"}))})))),editor.serializer.addNodeFilter("tiny-svg-block",(nodes=>nodes.forEach((node=>{node.unwrap()}))))}))}}));
//# sourceMappingURL=content.min.js.map
\ No newline at end of file
diff --git a/public/lib/editor/tiny/amd/build/content.min.js.map b/public/lib/editor/tiny/amd/build/content.min.js.map
index 492e9483d90..e4a2afa967b 100644
--- a/public/lib/editor/tiny/amd/build/content.min.js.map
+++ b/public/lib/editor/tiny/amd/build/content.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"content.min.js","sources":["../src/content.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 * Module to assist with creation and management of content.\n *\n * @module editor_tiny/content\n * @copyright Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Add MathML support to the editor.\n *\n * @param {TinyMCE} editor\n */\nexport const addMathMLSupport = (editor) => {\n const getNodeType = (node) => {\n const style = node.attr('style');\n if (style?.includes('display')) {\n if (style.match(/display:[^;]*inline/)) {\n return 'tiny-math-span';\n }\n }\n return 'tiny-math-block';\n };\n\n\n editor.on('PreInit', () => {\n editor.schema.addCustomElements({\n // Add support for MathML by defining some tiny-math blocks which extends SPAN/DIV.\n // Note: This is blind support and does not check the child content.\n // Any invalid markup will be accepted.\n // Note: We use the same names as the Tiny Premium Math plugin to avoid conflicts if both are enabled.\n math: {\n 'extends': 'div',\n },\n 'tiny-math-span': {\n 'extends': \"span\",\n },\n 'tiny-math-block': {\n 'extends': \"div\",\n },\n });\n\n // Add a Parser filter to wrap math nodes in a tiny-math-[block|span] element.\n editor.parser.addNodeFilter('math', (nodes) => nodes.forEach((node) => {\n if (node.parent) {\n if (node.parent.name === 'tiny-math-block' || node.parent.name === 'tiny-math-span') {\n // Already wrapped.\n return;\n }\n }\n\n const displayMode = getNodeType(node);\n node.wrap(editor.editorManager.html.Node.create(displayMode, {\n contenteditable: 'false',\n }));\n }));\n\n // Add a Serializer filter to remove the tiny-math-[block|span] wrapper.\n editor.serializer.addNodeFilter('tiny-math-span, tiny-math-block', (nodes, name) => nodes.forEach((node) => {\n const displayMode = name.replace('tiny-math-', '');\n node.children().forEach((child) => {\n const currentStyle = child.attr('style');\n if (currentStyle) {\n child.attr('style', `${currentStyle};display: ${displayMode}`);\n } else {\n child.attr('style', `display: ${displayMode}`);\n }\n });\n node.unwrap();\n }));\n });\n};\n\n/**\n * Add SVG support to the editor.\n *\n * @param {TinyMCE} editor\n */\nexport const addSVGSupport = (editor) => {\n editor.on('PreInit', () => {\n editor.schema.addCustomElements({\n // Add support for SVG by defining an SVG tag which extends DIV.\n // Note: This is blind support and does not check the child content.\n // Any invalid markup will be accepted.\n svg: {\n 'extends': \"div\",\n },\n 'tiny-svg-block': {\n 'extends': \"div\",\n },\n });\n\n editor.parser.addNodeFilter('svg', (nodes) => nodes.forEach((node) => {\n node.wrap(editor.editorManager.html.Node.create('tiny-svg-block', {\n contenteditable: 'false',\n }));\n }));\n editor.serializer.addNodeFilter('tiny-svg-block', (nodes) => nodes.forEach((node) => {\n node.unwrap();\n }));\n });\n};\n"],"names":["editor","on","schema","addCustomElements","math","parser","addNodeFilter","nodes","forEach","node","parent","name","displayMode","style","attr","includes","match","getNodeType","wrap","editorManager","html","Node","create","contenteditable","serializer","replace","children","child","currentStyle","unwrap","svg"],"mappings":"uMA4BiCA,SAY7BA,OAAOC,GAAG,WAAW,KACjBD,OAAOE,OAAOC,kBAAkB,CAK5BC,KAAM,SACS,wBAEG,SACH,0BAEI,SACJ,SAKnBJ,OAAOK,OAAOC,cAAc,QAASC,OAAUA,MAAMC,SAASC,UACtDA,KAAKC,SACoB,oBAArBD,KAAKC,OAAOC,MAAmD,mBAArBF,KAAKC,OAAOC,mBAMxDC,YArCOH,CAAAA,aACXI,MAAQJ,KAAKK,KAAK,gBACpBD,MAAAA,OAAAA,MAAOE,SAAS,YACZF,MAAMG,MAAM,uBACL,iBAGR,mBA8BiBC,CAAYR,MAChCA,KAAKS,KAAKlB,OAAOmB,cAAcC,KAAKC,KAAKC,OAAOV,YAAa,CACzDW,gBAAiB,gBAKzBvB,OAAOwB,WAAWlB,cAAc,mCAAmC,CAACC,MAAOI,OAASJ,MAAMC,SAASC,aACzFG,YAAcD,KAAKc,QAAQ,aAAc,IAC/ChB,KAAKiB,WAAWlB,SAASmB,cACfC,aAAeD,MAAMb,KAAK,SAC5Bc,aACAD,MAAMb,KAAK,kBAAYc,kCAAyBhB,cAEhDe,MAAMb,KAAK,2BAAqBF,iBAGxCH,KAAKoB,yCAUa7B,SAC1BA,OAAOC,GAAG,WAAW,KACjBD,OAAOE,OAAOC,kBAAkB,CAI5B2B,IAAK,SACU,wBAEG,SACH,SAInB9B,OAAOK,OAAOC,cAAc,OAAQC,OAAUA,MAAMC,SAASC,OACzDA,KAAKS,KAAKlB,OAAOmB,cAAcC,KAAKC,KAAKC,OAAO,iBAAkB,CAC9DC,gBAAiB,gBAGzBvB,OAAOwB,WAAWlB,cAAc,kBAAmBC,OAAUA,MAAMC,SAASC,OACxEA,KAAKoB"}
\ No newline at end of file
+{"version":3,"file":"content.min.js","sources":["../src/content.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 * Module to assist with creation and management of content.\n *\n * @module editor_tiny/content\n * @copyright Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Add MathML support to the editor.\n *\n * @param {TinyMCE} editor\n */\nexport const addMathMLSupport = (editor) => {\n const getNodeType = (node) => {\n const style = node.attr('style');\n if (style?.includes('display')) {\n if (style.match(/display:[^;]*inline/)) {\n return 'tiny-math-span';\n }\n }\n return 'tiny-math-block';\n };\n\n\n editor.on('PreInit', () => {\n editor.schema.addCustomElements({\n // Add support for MathML by defining some tiny-math blocks which extends SPAN/DIV.\n // Note: This is blind support and does not check the child content.\n // Any invalid markup will be accepted.\n // Note: We use the same names as the Tiny Premium Math plugin to avoid conflicts if both are enabled.\n math: {\n 'extends': 'div',\n },\n 'tiny-math-span': {\n 'extends': \"span\",\n },\n 'tiny-math-block': {\n 'extends': \"div\",\n },\n });\n\n // Add a Parser filter to wrap math nodes in a tiny-math-[block|span] element.\n editor.parser.addNodeFilter('math', (nodes) => nodes.forEach((node) => {\n if (node.parent) {\n if (node.parent.name === 'tiny-math-block' || node.parent.name === 'tiny-math-span') {\n // Already wrapped.\n return;\n }\n }\n\n const displayMode = getNodeType(node);\n node.wrap(editor.editorManager.html.Node.create(displayMode, {\n contenteditable: 'false',\n }));\n }));\n\n // Add a Serializer filter to remove the tiny-math-[block|span] wrapper.\n editor.serializer.addNodeFilter('tiny-math-span, tiny-math-block', (nodes, name) => nodes.forEach((node) => {\n const displayMode = name.replace('tiny-math-', '');\n node.children().forEach((child) => {\n const currentStyle = child.attr('style');\n if (currentStyle) {\n child.attr('style', `${currentStyle};display: ${displayMode}`);\n } else {\n child.attr('style', `display: ${displayMode}`);\n }\n });\n node.unwrap();\n }));\n });\n};\n\n/**\n * Add SVG support to the editor.\n *\n * @param {TinyMCE} editor\n */\nexport const addSVGSupport = (editor) => {\n editor.on('PreInit', () => {\n editor.schema.addCustomElements({\n // Add support for SVG by defining an SVG tag which extends DIV.\n // Note: This is blind support and does not check the child content.\n // Any invalid markup will be accepted.\n svg: {\n 'extends': \"div\",\n 'attributes': [\n \"id\",\n \"tabindex\",\n \"lang\",\n \"xml:space\",\n \"class\",\n \"style\",\n \"x\",\n \"y\",\n \"width\",\n \"height\",\n \"viewBox\",\n \"preserveAspectRatio\",\n \"transform\",\n ],\n },\n 'tiny-svg-block': {\n 'extends': \"div\",\n },\n });\n\n editor.parser.addNodeFilter('svg', (nodes) => nodes.forEach((node) => {\n node.wrap(editor.editorManager.html.Node.create('tiny-svg-block', {\n contenteditable: 'false',\n }));\n }));\n editor.serializer.addNodeFilter('tiny-svg-block', (nodes) => nodes.forEach((node) => {\n node.unwrap();\n }));\n });\n};\n"],"names":["editor","on","schema","addCustomElements","math","parser","addNodeFilter","nodes","forEach","node","parent","name","displayMode","style","attr","includes","match","getNodeType","wrap","editorManager","html","Node","create","contenteditable","serializer","replace","children","child","currentStyle","unwrap","svg"],"mappings":"uMA4BiCA,SAY7BA,OAAOC,GAAG,WAAW,KACjBD,OAAOE,OAAOC,kBAAkB,CAK5BC,KAAM,SACS,wBAEG,SACH,0BAEI,SACJ,SAKnBJ,OAAOK,OAAOC,cAAc,QAASC,OAAUA,MAAMC,SAASC,UACtDA,KAAKC,SACoB,oBAArBD,KAAKC,OAAOC,MAAmD,mBAArBF,KAAKC,OAAOC,mBAMxDC,YArCOH,CAAAA,aACXI,MAAQJ,KAAKK,KAAK,gBACpBD,MAAAA,OAAAA,MAAOE,SAAS,YACZF,MAAMG,MAAM,uBACL,iBAGR,mBA8BiBC,CAAYR,MAChCA,KAAKS,KAAKlB,OAAOmB,cAAcC,KAAKC,KAAKC,OAAOV,YAAa,CACzDW,gBAAiB,gBAKzBvB,OAAOwB,WAAWlB,cAAc,mCAAmC,CAACC,MAAOI,OAASJ,MAAMC,SAASC,aACzFG,YAAcD,KAAKc,QAAQ,aAAc,IAC/ChB,KAAKiB,WAAWlB,SAASmB,cACfC,aAAeD,MAAMb,KAAK,SAC5Bc,aACAD,MAAMb,KAAK,kBAAYc,kCAAyBhB,cAEhDe,MAAMb,KAAK,2BAAqBF,iBAGxCH,KAAKoB,yCAUa7B,SAC1BA,OAAOC,GAAG,WAAW,KACjBD,OAAOE,OAAOC,kBAAkB,CAI5B2B,IAAK,SACU,iBACG,CACV,KACA,WACA,OACA,YACA,QACA,QACA,IACA,IACA,QACA,SACA,UACA,sBACA,+BAGU,SACH,SAInB9B,OAAOK,OAAOC,cAAc,OAAQC,OAAUA,MAAMC,SAASC,OACzDA,KAAKS,KAAKlB,OAAOmB,cAAcC,KAAKC,KAAKC,OAAO,iBAAkB,CAC9DC,gBAAiB,gBAGzBvB,OAAOwB,WAAWlB,cAAc,kBAAmBC,OAAUA,MAAMC,SAASC,OACxEA,KAAKoB"}
\ No newline at end of file
diff --git a/public/lib/editor/tiny/amd/src/content.js b/public/lib/editor/tiny/amd/src/content.js
index 0801c942740..15ec9e8dc0a 100644
--- a/public/lib/editor/tiny/amd/src/content.js
+++ b/public/lib/editor/tiny/amd/src/content.js
@@ -99,6 +99,21 @@ export const addSVGSupport = (editor) => {
// Any invalid markup will be accepted.
svg: {
'extends': "div",
+ 'attributes': [
+ "id",
+ "tabindex",
+ "lang",
+ "xml:space",
+ "class",
+ "style",
+ "x",
+ "y",
+ "width",
+ "height",
+ "viewBox",
+ "preserveAspectRatio",
+ "transform",
+ ],
},
'tiny-svg-block': {
'extends': "div",
diff --git a/public/lib/editor/tiny/tests/behat/svg.feature b/public/lib/editor/tiny/tests/behat/svg.feature
new file mode 100644
index 00000000000..2bcf06645a8
--- /dev/null
+++ b/public/lib/editor/tiny/tests/behat/svg.feature
@@ -0,0 +1,17 @@
+@editor @editor_tiny @javascript
+Feature: Use SVG elements in TinyMCE
+ In order to use SVG elements in TinyMCE
+ As a user
+ I need to be able to specify how they appear
+
+ Scenario: SVG attributes are respected when saving source code
+ Given I am on the "Profile advanced editing" page logged in as "admin"
+ When I set the field "Description" to multiline:
+ """
+
+ """
+ And I click on the "Tools > Source code" menu item for the "Description" TinyMCE editor
+ And I click on "Save" "button"
+ Then the field "Description" matches expression "##s"