Aller au contenu

« MediaWiki:Common.js » : différence entre les versions

De Loic Wiki
Ajout du support D2 dans Common.js
Correction du rendu D2 via Kroki
 
Ligne 79 : Ligne 79 :
   }
   }


   async function renderD2() {
   function renderD2() {
     var blocks = document.querySelectorAll('pre.oc-d2');
     var blocks = document.querySelectorAll('pre.oc-d2');
     if (!blocks.length) return;
     if (!blocks.length) return Promise.resolve();
     let D2Ctor;
     return Promise.all(Array.from(blocks).map(function (block) {
    try {
      if (block.dataset.ocRendered) return Promise.resolve();
      const mod = await import('https://esm.sh/@terrastruct/d2');
      D2Ctor = mod.D2;
    } catch (err) {
      blocks.forEach(function (block) {
        if (block.dataset.ocRendered) return;
        block.dataset.ocRendered = '1';
        var wrapper = document.createElement('div');
        wrapper.className = 'oc-diagram-error';
        wrapper.textContent = 'D2 import error: ' + String(err);
        block.parentNode.insertBefore(wrapper, block);
      });
      return;
    }
    const d2 = new D2Ctor();
    for (const block of blocks) {
      if (block.dataset.ocRendered) continue;
       block.dataset.ocRendered = '1';
       block.dataset.ocRendered = '1';
       const source = block.textContent.trim();
       var source = block.textContent.trim();
       const wrapper = document.createElement('div');
       var wrapper = document.createElement('div');
       wrapper.className = 'oc-diagram oc-d2-rendered';
       wrapper.className = 'oc-diagram oc-d2-rendered';
       block.style.display = 'none';
       block.style.display = 'none';
       block.parentNode.insertBefore(wrapper, block);
       block.parentNode.insertBefore(wrapper, block);
       try {
       return fetch('https://kroki.io/d2/svg', {
         const result = await d2.compile(source);
         method: 'POST',
         const svg = await d2.render(result.diagram, { themeID: 8, darkThemeID: 200 });
        headers: {
          'Content-Type': 'text/plain',
          'Accept': 'image/svg+xml'
        },
        body: source
      }).then(function (res) {
        if (!res.ok) throw new Error('HTTP ' + res.status);
         return res.text();
      }).then(function (svg) {
         wrapper.innerHTML = svg;
         wrapper.innerHTML = svg;
       } catch (err) {
       }).catch(function (err) {
         wrapper.innerHTML = '<div class="oc-diagram-error">D2 error: ' + escapeHtml(String(err)) + '</div>';
         wrapper.innerHTML = '<div class="oc-diagram-error">D2 error: ' + escapeHtml(String(err)) + '</div>';
       }
       });
     }
     }));
   }
   }



Dernière version du 19 mars 2026 à 23:10

(function () {
  function loadScript(src) {
    return new Promise(function (resolve, reject) {
      if ([].some.call(document.scripts, function (s) { return s.src === src; })) return resolve();
      var script = document.createElement('script');
      script.src = src;
      script.async = true;
      script.onload = resolve;
      script.onerror = reject;
      document.head.appendChild(script);
    });
  }

  function escapeHtml(str) {
    return str.replace(/[&<>"']/g, function (m) {
      return ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' })[m];
    });
  }

  function renderMermaid() {
    var blocks = document.querySelectorAll('pre.oc-mermaid');
    if (!blocks.length || !window.mermaid) return Promise.resolve();
    mermaid.initialize({ startOnLoad: false, securityLevel: 'loose', theme: 'default' });
    return Promise.all(Array.from(blocks).map(function (block, idx) {
      if (block.dataset.ocRendered) return Promise.resolve();
      block.dataset.ocRendered = '1';
      var wrapper = document.createElement('div');
      wrapper.className = 'oc-diagram oc-mermaid-rendered';
      var source = block.textContent.trim();
      block.style.display = 'none';
      block.parentNode.insertBefore(wrapper, block);
      return mermaid.render('oc-mermaid-' + idx + '-' + Date.now(), source).then(function (result) {
        wrapper.innerHTML = result.svg;
      }).catch(function (err) {
        wrapper.innerHTML = '<div class="oc-diagram-error">Mermaid error: ' + escapeHtml(String(err)) + '</div>';
      });
    }));
  }

  function renderPlantUML() {
    var blocks = document.querySelectorAll('pre.oc-plantuml');
    if (!blocks.length || !window.plantumlEncoder) return;
    blocks.forEach(function (block) {
      if (block.dataset.ocRendered) return;
      block.dataset.ocRendered = '1';
      var src = block.textContent.trim();
      var encoded = plantumlEncoder.encode(src);
      var img = document.createElement('img');
      img.className = 'oc-diagram oc-plantuml-rendered';
      img.alt = 'PlantUML diagram';
      img.src = 'https://kroki.io/plantuml/svg/' + encoded;
      var wrap = document.createElement('div');
      wrap.className = 'oc-diagram-wrap';
      wrap.appendChild(img);
      block.style.display = 'none';
      block.parentNode.insertBefore(wrap, block);
    });
  }

  function renderBPMN() {
    var blocks = document.querySelectorAll('.oc-bpmn-container');
    if (!blocks.length || !window.BpmnJS) return;
    blocks.forEach(function (container) {
      if (container.dataset.ocRendered) return;
      var source = container.querySelector('pre.oc-bpmn-xml');
      var mount = container.querySelector('.oc-bpmn-viewer');
      if (!source || !mount) return;
      container.dataset.ocRendered = '1';
      var xml = source.textContent.trim();
      source.style.display = 'none';
      var viewer = new BpmnJS({ container: mount, keyboard: { bindTo: document } });
      viewer.importXML(xml).then(function () {
        var canvas = viewer.get('canvas');
        canvas.zoom('fit-viewport', 'auto');
      }).catch(function (err) {
        mount.innerHTML = '<div class="oc-diagram-error">BPMN error: ' + escapeHtml(String(err)) + '</div>';
      });
    });
  }

  function renderD2() {
    var blocks = document.querySelectorAll('pre.oc-d2');
    if (!blocks.length) return Promise.resolve();
    return Promise.all(Array.from(blocks).map(function (block) {
      if (block.dataset.ocRendered) return Promise.resolve();
      block.dataset.ocRendered = '1';
      var source = block.textContent.trim();
      var wrapper = document.createElement('div');
      wrapper.className = 'oc-diagram oc-d2-rendered';
      block.style.display = 'none';
      block.parentNode.insertBefore(wrapper, block);
      return fetch('https://kroki.io/d2/svg', {
        method: 'POST',
        headers: {
          'Content-Type': 'text/plain',
          'Accept': 'image/svg+xml'
        },
        body: source
      }).then(function (res) {
        if (!res.ok) throw new Error('HTTP ' + res.status);
        return res.text();
      }).then(function (svg) {
        wrapper.innerHTML = svg;
      }).catch(function (err) {
        wrapper.innerHTML = '<div class="oc-diagram-error">D2 error: ' + escapeHtml(String(err)) + '</div>';
      });
    }));
  }

  function boot() {
    Promise.all([
      loadScript('https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js'),
      loadScript('https://cdn.jsdelivr.net/npm/plantuml-encoder/dist/plantuml-encoder.min.js'),
      loadScript('https://cdn.jsdelivr.net/npm/bpmn-js@18/dist/bpmn-navigated-viewer.production.min.js')
    ]).then(function () {
      return renderMermaid();
    }).then(function () {
      renderPlantUML();
      renderBPMN();
      return renderD2();
    }).catch(function (err) {
      console.error('Diagram integration failed', err);
    });
  }

  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot);
  else boot();
})();