Examples › Track 3 — Editor › Example 11

Custom fences in editor

The editor's customFences option lets you register render functions for any fence type. Below: a chart fence that takes simple label,value rows and renders a styled bar chart — no Chart.js or D3 required.

Live editor with the custom fence

The plugin code

function renderChartFence(code, _lang) {
  // Parse "label,value" rows
  const rows = code.trim().split('\n')
    .map(line => line.split(',').map(s => s.trim()))
    .filter(([label, value]) => label && value);

  const max = Math.max(...rows.map(([, v]) => parseFloat(v)));

  const bars = rows.map(([label, value]) => {
    const pct = (parseFloat(value) / max) * 100;
    return `<div class="qd-bar-row">
      <span class="qd-bar-label">${label}</span>
      <div class="qd-bar-track"><div class="qd-bar-fill" style="width:${pct}%"></div></div>
      <span class="qd-bar-value">${value}</span>
    </div>`;
  }).join('');

  return `<div class="qd-bar-chart" data-qd-fence="\`\`\`" data-qd-lang="chart" data-qd-source="${
    code.replace(/"/g, '&quot;').replace(/</g, '&lt;')
  }">${bars}</div>`;
}

new QuikdownEditor('#editor', {
  customFences: { chart: renderChartFence }
});

What to know

  • The customFences object maps fence language names to render functions: (code, lang) => htmlString.
  • Set data-qd-source on your output element so the editor's bidirectional reverse-conversion can read the original source back when the user edits other parts of the document.
  • Custom fence containers are marked contenteditable="false" automatically — clicking them won't break the editor's contenteditable preview.
  • This is exactly how the built-in SVG, CSV, math, mermaid, GeoJSON, and STL fence renderers work internally.