title: Embed html FlameGraph into Azure wiki
body: <p>I need to embed app Flame Graph into Azure Devops wiki page.</p>
  
  <p>FlameGraph is an visualization of an app's call stack in a very simple and understandable form. Physically it is a SVG image which is rendered by browser like this (clickable):</p>
  
  <p><a href="https://queue.acm.org/downloads/2016/Gregg5.svg" rel="nofollow noreferrer"><img src="https://queue.acm.org/downloads/2016/Gregg5.svg" alt=""></a></p>
  
  <p>However, I want to embed not a usual FlameGraph, but a HTML graph which is a huge piece of 70K+ HTML and JS lines. This code having rendered looks totally like SVG, here is the sample</p>
  
  <pre><code>&lt;g id="" class="func_g" onmouseover="s(this, '', 'perf')" onmouseout="c('', 'perf')" 
  onclick="zoom(this, 'perf')" &gt;
  &lt;title&gt;consular_function&lt;/title&gt;
  &lt;rect x="531.6" y="398" width="0.6" height="15.0" fill="rgb(220,220,220)" rx="2.2" ry="2.2" /&gt;
  &lt;text text-anchor="" x="534.61" y="408.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)"  &gt; 
  &lt;/text&gt;
  &lt;/g&gt;
  &lt;g id="" class="func_g" onmouseover="s(this, '', 'perf')" onmouseout="c('', 'perf')" 
  onclick="zoom(this, 'perf')" &gt;
  &lt;title&gt;db_function&lt;/title&gt;
  &lt;rect x="1367.2" y="446" width="0.1" height="15.0" fill="rgb(130,202,250)" rx="2.2" ry="2.2" /&gt;
  &lt;text text-anchor="" x="1370.18" y="456.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)"  &gt; 
  &lt;/text&gt;
  &lt;/g&gt;
  &lt;g id="" class="func_g" onmouseover="s(this, '', 'perf')" onmouseout="c('', 'perf')" onclick="zoom(this, 'perf')" &gt; 
  &lt;title&gt;db_function&lt;/title&gt;
  &lt;rect x="1402.0" y="414" width="1.7" height="15.0" fill="rgb(130,202,250)" rx="2.2" ry="2.2" /&gt;
  &lt;text text-anchor="" x="1405.03" y="424.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)"  &gt; 
  &lt;/text&gt;
  &lt;/g&gt;
  &lt;g id="" class="func_g" onmouseover="s(this, '', 'perf')" onmouseout="c('', 'perf')" 
  onclick="zoom(this, 'perf')" &gt;
  &lt;title&gt;consular_function&lt;/title&gt;
  &lt;rect x="1037.6" y="302" width="4.6" height="15.0" fill="rgb(220,220,220)" rx="2.2" ry="2.2" /&gt;
  &lt;text text-anchor="" x="1040.59" y="312.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)"  &gt; 
  &lt;/text&gt;
  &lt;/g&gt;
  &lt;g id="" class="func_g" onmouseover="s(this, '', 'perf')" onmouseout="c('', 'perf')" 
  onclick="zoom(this, 'perf')" &gt;
  &lt;title&gt;moduled_function (3,218 us, 0,04%)&lt;/title&gt;
  &lt;rect x="10.8" y="494" width="0.7" height="15.0" fill="rgb(237,110,36)" rx="2.2" ry="2.2" /&gt;
  &lt;text text-anchor="" x="13.78" y="504.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)"  &gt; 
  &lt;/text&gt;
  &lt;/g&gt;
  &lt;defs &gt;
      &lt;linearGradient id="background_mem" y1="0" y2="1" x1="0" x2="0" &gt;
          &lt;stop stop-color="#eeeeef" offset="10%" /&gt;
          &lt;stop stop-color="#eeeee0" offset="90%" /&gt;
      &lt;/linearGradient&gt;
  &lt;/defs&gt;
  &lt;style type="text/css"&gt;
      .func_g:hover { stroke:black; stroke-width:0.5; cursor:pointer; }
  &lt;/style&gt;
  
  
  &lt;/svg&gt;
  
  &lt;script type="text/ecmascript"&gt;
      // Javascript for svg file
      // Used to control flame graph operations, e.g. zoom in/out, search, etc
      if(typeof window.flameGraph == "undefined") window.flameGraph={};                     // global flame graph elements (contained width, it is a hashmap for each svgId)
      if(typeof window.searchButton == "undefined") window.searchButton={};                 // global searching button hashmap for each svgId
      if(typeof window.detailedTextField == "undefined") window.detailedTextField={};       // global detailed text box (on the bottom of graph) hashmap for each svgId
      if(typeof window.matchedTextField == "undefined") window.matchedTextField={};         // global matched text box (on the right of detailed text box) hashmap for each svgId
      if(typeof window.isSearching == "undefined") window.isSearching={};                   // global hashmap for each svg whether it is in searching mode or not
      if(typeof window.revertGraph == "undefined") window.revertGraph={};                   // global hashmap for each svg whether the flame graph is reverted or not
  
      revertGraph['mem'] = 0;
      function init(evt, hlString, svgId) { //init function used to initialize the variables
          if(svgId == undefined) return;
          flameGraph[svgId] = document.getElementById(svgId).getAttribute("svg_width");   // get flame graph width by internal svg label "svg_width"
          searchButton[svgId] = document.getElementById(svgId + "_search");               // get search button
          detailedTextField[svgId] = document.getElementById(svgId + "_details").firstChild;      // get details text box
          matchedTextField[svgId] = document.getElementById(svgId + "_matched");  // get matched text box 
          isSearching[svgId] = 0;        // not searching
          if(hlString.length != 0) search(hlString, svgId); // if needed -&gt; highlight string with search function when creating flame graph 
      }
      init(null, '', 'mem'); 
  
      function jumpToPage(title) { // jump to formatted dev trace page
          var reg = new RegExp('(?&lt;=w)([0-9]+)(?=\\s\\()');
          var pageNo = reg.exec(title);
          if(pageNo == null) {alert('target not found.'); return;}
          showDevTrace('' + pageNo[0] + '_html');
      }
      function s(node, id, svgId) { // mouse-over action
          detailedTextField[svgId].nodeValue = "" + getTitleText(node);  // show the text of current choosing node
          if(id.length != 0) window.parent.highlightFrame(id);
      }
      function c(id, svgId) { // mouse-out action
          detailedTextField[svgId].nodeValue = ' ';
          if(id.length != 0) window.parent.unhighlightFrame(id);
      }
      function getTitleText(e) { //return the title string of the e node
          var text = findChild(e, "title").firstChild.nodeValue;
          return (text);
      }
      function findChild(e, name, attr) { // looking for the child (of e) whose name is equal to "name"
          var children = e.childNodes;
          for(var i=0; i&lt;children.length;i++) {
              if(children[i].tagName == name) { 
                  if(attr == undefined) return children[i]; //return the child node
                  else children[i].attributes[attr].value; // if attr is inputed, return the attr value of this child node
              }
          }
          return;
      }
  
  table, th, td {
      background-color: #FFFFF1;
      padding: 7px;
      border: 1px solid black;
      border-collapse: collapse;
      overflow: visible;
      font-size: 12px;
      alig: left;
  }
  &lt;style&gt;&lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>full code is too big so I put full working sample <a href="https://jsfiddle.net/jed4y9qk/embedded/result" rel="nofollow noreferrer">into a fiddle</a>.</p>
  
  <p>I tried to put HTML/JS lines directly into Azure page but it does not render this code showing it like plain-text, for simple HTML like tables and lists Azure works though.</p>
  
  <p>How to embed this piece into Azure? I know that iframe <a href="https://developercommunity.visualstudio.com/idea/608314/allow-iframe-elements-to-be-embedded-in-wiki-pages.html?inRegister=true" rel="nofollow noreferrer">is still not supported</a> but maybe there is another way?</p>
  
  <p>P.S. Maybe there is way to convert html-rendered graph into SVG, does Azure renders such SVG correctly?</p>