Aller au contenu

MediaWiki:Common.js

De Loic Wiki
Version datée du 19 mars 2026 à 23:00 par Maintenance script (discussion | contributions) (Ajout du support D2 dans Common.js)

Note : après avoir publié vos modifications, il se peut que vous deviez forcer le rechargement complet du cache de votre navigateur pour voir les changements.

  • Firefox / Safari : maintenez la touche Maj (Shift) en cliquant sur le bouton Actualiser ou appuyez sur Ctrl + F5 ou Ctrl + R (⌘ + R sur un Mac).
  • Google Chrome : appuyez sur Ctrl + Maj + R (⌘ + Shift + R sur un Mac).
  •  Edge : maintenez la touche Ctrl en cliquant sur le bouton Actualiser ou pressez Ctrl + F5.
(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>';
      });
    });
  }

  async function renderD2() {
    var blocks = document.querySelectorAll('pre.oc-d2');
    if (!blocks.length) return;
    let D2Ctor;
    try {
      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';
      const source = block.textContent.trim();
      const wrapper = document.createElement('div');
      wrapper.className = 'oc-diagram oc-d2-rendered';
      block.style.display = 'none';
      block.parentNode.insertBefore(wrapper, block);
      try {
        const result = await d2.compile(source);
        const svg = await d2.render(result.diagram, { themeID: 8, darkThemeID: 200 });
        wrapper.innerHTML = svg;
      } catch (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();
})();