diff --git a/bindings/jupyroot/python/JupyROOT/helpers/utils.py b/bindings/jupyroot/python/JupyROOT/helpers/utils.py index 98c191eb7968a..f853179daf9fe 100644 --- a/bindings/jupyroot/python/JupyROOT/helpers/utils.py +++ b/bindings/jupyroot/python/JupyROOT/helpers/utils.py @@ -74,7 +74,7 @@ // We are in jupyter notebooks, use require.js which should be configured already requirejs.config({{ - paths: {{ 'JSRootCore' : [ 'build/jsroot', 'https://root.cern/js/7.9.0/build/jsroot', 'https://jsroot.gsi.de/7.9.0/build/jsroot' ] }} + paths: {{ 'JSRootCore' : [ 'build/jsroot', 'https://root.cern/js/7.9.3/build/jsroot', 'https://jsroot.gsi.de/7.9.3/build/jsroot' ] }} }})(['JSRootCore'], function(Core) {{ display_{jsDivId}(Core); }}); @@ -97,7 +97,7 @@ // Try loading a local version of requirejs and fallback to cdn if not possible. script_load_{jsDivId}(base_url + 'static/build/jsroot.js', function(){{ console.error('Fail to load JSROOT locally, please check your jupyter_notebook_config.py file'); - script_load_{jsDivId}('https://root.cern/js/7.9.0/build/jsroot.js', function(){{ + script_load_{jsDivId}('https://root.cern/js/7.9.3/build/jsroot.js', function(){{ document.getElementById("{jsDivId}").innerHTML = "Failed to load JSROOT"; }}); }}); diff --git a/js/build/jsroot.js b/js/build/jsroot.js index 84525ea2a30ef..f208d21aea616 100644 --- a/js/build/jsroot.js +++ b/js/build/jsroot.js @@ -8,11 +8,11 @@ typeof define === 'function' && define.amd ? define(['exports'], factory) : var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null; /** @summary version id * @desc For the JSROOT release the string in format 'major.minor.patch' like '7.0.0' */ -const version_id = '7.9.x', +const version_id = '7.9.3', /** @summary version date * @desc Release date in format day/month/year like '14/04/2022' */ -version_date = '14/10/2025', +version_date = '21/10/2025', /** @summary version id and date * @desc Produced by concatenation of {@link version_id} and {@link version_date} @@ -13903,24 +13903,24 @@ function drawRawText(dom, txt /* , opt */) { if (!isStr(stxt)) stxt = ''; - const mathjax = this.txt.mathjax || (settings.Latex === constants$1.Latex.AlwaysMathJax); - - if (!mathjax && !('as_is' in this.txt)) { - const arr = stxt.split('\n'); - stxt = ''; - for (let i = 0; i < arr.length; ++i) - stxt += `
${arr[i]}
`; - } - - const frame = this.selectDom(); + const mathjax = this.txt.mathjax || (settings.Latex === constants$1.Latex.AlwaysMathJax), + frame = this.selectDom(); let main = frame.select('div'); if (main.empty()) main = frame.append('div').attr('style', 'max-width:100%;max-height:100%;overflow:auto'); - main.html(stxt); + else + main.html(''); // (re) set painter to first child element, base painter not requires canvas this.setTopPainter(); + if (!mathjax && !('as_is' in this.txt)) { + const arr = stxt.split('\n'); + for (let i = 0; i < arr.length; ++i) + main.append('pre').style('margin', '0').text(arr[i]); + } else + main.text(stxt); + if (mathjax) typesetMathjax(frame.node()); @@ -71015,7 +71015,7 @@ class StandaloneMenu extends JSRootMenu { text.style.display = 'flex'; const chk = doc.createElement('span'); - chk.innerHTML = d.checked ? '\u2713' : ''; + chk.innerText = d.checked ? '\u2713' : ''; chk.style.display = 'inline-block'; chk.style.width = '1em'; text.appendChild(chk); @@ -71028,7 +71028,7 @@ class StandaloneMenu extends JSRootMenu { } else { if (need_check_area) { const chk = doc.createElement('span'); - chk.innerHTML = d.checked ? '\u2713' : ''; + chk.innerText = d.checked ? '\u2713' : ''; chk.style.display = 'inline-block'; chk.style.width = '1em'; text.appendChild(chk); @@ -76863,10 +76863,12 @@ class FlexibleDisplay extends MDIDisplay { main = top.append('div'); main.html('
' + - `

${title}

`+ - `
`+ + '

' + + `
` + '
'); + main.select('.jsroot_flex_header p').text(title); + main.attr('class', 'jsroot_flex_frame') .style('position', 'absolute') .style('left', Math.round(w * (this.cnt % 5)/10) + 'px') @@ -155421,7 +155423,7 @@ function objectHierarchy(top, obj, args = undefined) { item._vclass = cssValueNum; } else if (isStr(fld)) { simple = true; - item._value = '"' + fld.replace(/&/g, '&').replace(/"/g, '"').replace(//g, '>') + '"'; + item._value = '"' + fld + '"'; item._vclass = 'h_value_str'; } else if (typeof fld === 'undefined') { simple = true; @@ -156216,8 +156218,10 @@ class HierarchyPainter extends BasePainter { if ('_value' in hitem) { const d3p = d3line.append('p'); - if ('_vclass' in hitem) d3p.attr('class', hitem._vclass); - if (!hitem._isopen) d3p.html(hitem._value); + if ('_vclass' in hitem) + d3p.attr('class', hitem._vclass); + if (!hitem._isopen) + d3p.text(hitem._value); } if (has_childs && (isroot || hitem._isopen)) { @@ -158795,7 +158799,7 @@ class HierarchyPainter extends BasePainter { const layout = main.select('.gui_layout'); if (!layout.empty()) { ['simple', 'vert2', 'vert3', 'vert231', 'horiz2', 'horiz32', 'flex', 'tabs', - 'grid 2x2', 'grid 1x3', 'grid 2x3', 'grid 3x3', 'grid 4x4'].forEach(kind => layout.append('option').attr('value', kind).html(kind)); + 'grid 2x2', 'grid 1x3', 'grid 2x3', 'grid 3x3', 'grid 4x4'].forEach(kind => layout.append('option').attr('value', kind).text(kind)); layout.on('change', ev => { const kind = ev.target.value || 'flex'; @@ -158835,7 +158839,7 @@ class HierarchyPainter extends BasePainter { } if (!found) { const opt = document.createElement('option'); - opt.innerHTML = opt.value = this.getLayout(); + opt.innerText = opt.value = this.getLayout(); selects.appendChild(opt); selects.selectedIndex = selects.options.length - 1; } diff --git a/js/changes.md b/js/changes.md index d198c2898c5c0..0b6a1612c7215 100644 --- a/js/changes.md +++ b/js/changes.md @@ -1,7 +1,9 @@ # JSROOT changelog -## Changes in 7.9.x +## Changes in 7.9.3 1. Fix - store large PDF with 3D drawing inside +2. Fix - prevent JS code injection via `TObjString` drawing +3. Fix - reduce use of HTML in hpainter, display and menu components ## Changes in 7.9.2 diff --git a/js/modules/base/ObjectPainter.mjs b/js/modules/base/ObjectPainter.mjs index 05b66332ec0e2..6463c4b372beb 100644 --- a/js/modules/base/ObjectPainter.mjs +++ b/js/modules/base/ObjectPainter.mjs @@ -1642,24 +1642,24 @@ function drawRawText(dom, txt /* , opt */) { if (!isStr(stxt)) stxt = ''; - const mathjax = this.txt.mathjax || (settings.Latex === constants.Latex.AlwaysMathJax); - - if (!mathjax && !('as_is' in this.txt)) { - const arr = stxt.split('\n'); - stxt = ''; - for (let i = 0; i < arr.length; ++i) - stxt += `
${arr[i]}
`; - } - - const frame = this.selectDom(); + const mathjax = this.txt.mathjax || (settings.Latex === constants.Latex.AlwaysMathJax), + frame = this.selectDom(); let main = frame.select('div'); if (main.empty()) main = frame.append('div').attr('style', 'max-width:100%;max-height:100%;overflow:auto'); - main.html(stxt); + else + main.html(''); // (re) set painter to first child element, base painter not requires canvas this.setTopPainter(); + if (!mathjax && !('as_is' in this.txt)) { + const arr = stxt.split('\n'); + for (let i = 0; i < arr.length; ++i) + main.append('pre').style('margin', '0').text(arr[i]); + } else + main.text(stxt); + if (mathjax) typesetMathjax(frame.node()); diff --git a/js/modules/core.mjs b/js/modules/core.mjs index e21cc26dd06d4..6216d7279a1a4 100644 --- a/js/modules/core.mjs +++ b/js/modules/core.mjs @@ -1,10 +1,10 @@ /** @summary version id * @desc For the JSROOT release the string in format 'major.minor.patch' like '7.0.0' */ -const version_id = '7.9.x', +const version_id = '7.9.3', /** @summary version date * @desc Release date in format day/month/year like '14/04/2022' */ -version_date = '14/10/2025', +version_date = '21/10/2025', /** @summary version id and date * @desc Produced by concatenation of {@link version_id} and {@link version_date} diff --git a/js/modules/gui/HierarchyPainter.mjs b/js/modules/gui/HierarchyPainter.mjs index b26544ade6de1..d0141b10e2f43 100644 --- a/js/modules/gui/HierarchyPainter.mjs +++ b/js/modules/gui/HierarchyPainter.mjs @@ -509,7 +509,7 @@ function objectHierarchy(top, obj, args = undefined) { item._vclass = cssValueNum; } else if (isStr(fld)) { simple = true; - item._value = '"' + fld.replace(/&/g, '&').replace(/"/g, '"').replace(//g, '>') + '"'; + item._value = '"' + fld + '"'; item._vclass = 'h_value_str'; } else if (typeof fld === 'undefined') { simple = true; @@ -1306,8 +1306,10 @@ class HierarchyPainter extends BasePainter { if ('_value' in hitem) { const d3p = d3line.append('p'); - if ('_vclass' in hitem) d3p.attr('class', hitem._vclass); - if (!hitem._isopen) d3p.html(hitem._value); + if ('_vclass' in hitem) + d3p.attr('class', hitem._vclass); + if (!hitem._isopen) + d3p.text(hitem._value); } if (has_childs && (isroot || hitem._isopen)) { @@ -3885,7 +3887,7 @@ class HierarchyPainter extends BasePainter { const layout = main.select('.gui_layout'); if (!layout.empty()) { ['simple', 'vert2', 'vert3', 'vert231', 'horiz2', 'horiz32', 'flex', 'tabs', - 'grid 2x2', 'grid 1x3', 'grid 2x3', 'grid 3x3', 'grid 4x4'].forEach(kind => layout.append('option').attr('value', kind).html(kind)); + 'grid 2x2', 'grid 1x3', 'grid 2x3', 'grid 3x3', 'grid 4x4'].forEach(kind => layout.append('option').attr('value', kind).text(kind)); layout.on('change', ev => { const kind = ev.target.value || 'flex'; @@ -3925,7 +3927,7 @@ class HierarchyPainter extends BasePainter { } if (!found) { const opt = document.createElement('option'); - opt.innerHTML = opt.value = this.getLayout(); + opt.innerText = opt.value = this.getLayout(); selects.appendChild(opt); selects.selectedIndex = selects.options.length - 1; } diff --git a/js/modules/gui/display.mjs b/js/modules/gui/display.mjs index 4fd94290c374b..1acec4fade8a0 100644 --- a/js/modules/gui/display.mjs +++ b/js/modules/gui/display.mjs @@ -933,10 +933,12 @@ class FlexibleDisplay extends MDIDisplay { main = top.append('div'); main.html('
' + - `

${title}

`+ - `
`+ + '

' + + `
` + '
'); + main.select('.jsroot_flex_header p').text(title); + main.attr('class', 'jsroot_flex_frame') .style('position', 'absolute') .style('left', Math.round(w * (this.cnt % 5)/10) + 'px') diff --git a/js/modules/gui/menu.mjs b/js/modules/gui/menu.mjs index fee8dfbf3a16a..9168050417808 100644 --- a/js/modules/gui/menu.mjs +++ b/js/modules/gui/menu.mjs @@ -1350,7 +1350,7 @@ class StandaloneMenu extends JSRootMenu { text.style.display = 'flex'; const chk = doc.createElement('span'); - chk.innerHTML = d.checked ? '\u2713' : ''; + chk.innerText = d.checked ? '\u2713' : ''; chk.style.display = 'inline-block'; chk.style.width = '1em'; text.appendChild(chk); @@ -1363,7 +1363,7 @@ class StandaloneMenu extends JSRootMenu { } else { if (need_check_area) { const chk = doc.createElement('span'); - chk.innerHTML = d.checked ? '\u2713' : ''; + chk.innerText = d.checked ? '\u2713' : ''; chk.style.display = 'inline-block'; chk.style.width = '1em'; text.appendChild(chk);