Examples › Track 2 — Bidirectional › Example 6
Reverse fence handlers
A fence plugin with render alone is forward-only — once the fence is rendered to HTML, the source is lost. Add a reverse(node) handler and the fence round-trips through quikdown_bd safely. Below: a custom quote fence that round-trips.
Live three-pane round-trip
1. Source
2. Rendered (editable)
3. Markdown back
The plugin
const quoteFencePlugin = {
// Forward: render the fence to HTML.
// Stash the original source on data-qd-source so reverse() can find it.
render(content, lang) {
if (lang !== 'quote') return undefined;
const escaped = content.replace(/"/g, '"');
return `<blockquote class="quote-card" data-qd-fence="\`\`\`" data-qd-lang="quote" data-qd-source="${escaped}">` +
content.trim() +
`</blockquote>`;
},
// Reverse: read the source attribute and reconstruct the fence.
reverse(node) {
if (!node.classList?.contains('quote-card')) return null;
const source = node.getAttribute('data-qd-source') || node.textContent;
return { fence: '\`\`\`', lang: 'quote', content: source };
}
};
// Use it on both forward and reverse calls — same plugin object.
const html = quikdown_bd(md, { fence_plugin: quoteFencePlugin });
const md2 = quikdown_bd.toMarkdown(htmlOrEl, { fence_plugin: quoteFencePlugin });